Category: aiml

  • Agentic Design Pattern: Escalation

    
        """
    Pattern 140: Escalation Pattern
    
    Description:
        The Escalation Pattern implements mechanisms for identifying situations that
        require human intervention or higher-level decision-making and routing them
        appropriately through an escalation hierarchy. This pattern recognizes when an
        agent encounters scenarios beyond its capabilities, authority, or confidence
        level and escalates to appropriate handlers based on severity and context.
    
        Escalation is critical for AI safety and reliability, ensuring that complex,
        high-stakes, or ambiguous situations receive appropriate human oversight. The
        pattern supports multiple escalation levels, severity assessment, automatic
        triggering based on rules or confidence thresholds, and routing to appropriate
        stakeholders. It balances agent autonomy with human control.
    
        This implementation provides a comprehensive escalation system with severity
        assessment, trigger conditions, escalation routing, stakeholder management,
        escalation tracking, and resolution workflows. It supports both rule-based
        and confidence-based escalation with customizable escalation paths.
    
    Components:
        - Severity Assessment: Evaluate situation severity
        - Trigger Detection: Identify when to escalate
        - Escalation Routing: Route to appropriate handler
        - Stakeholder Management: Manage escalation recipients
        - Escalation Tracking: Monitor escalation status
        - Resolution Workflow: Handle escalation lifecycle
    
    Use Cases:
        - High-stakes decisions (medical, financial, legal)
        - Low-confidence predictions
        - Policy violations
        - Security incidents
        - Customer complaints
        - System errors
        - Ethical dilemmas
        - Edge cases
    
    LangChain Implementation:
        This implementation uses:
        - LLM for severity assessment and decision complexity analysis
        - Rule-based escalation triggers
        - Confidence-threshold escalation
        - Hierarchical escalation routing
        - Escalation event tracking
        - Integration with human-in-the-loop systems
    
    Benefits:
        - Ensures human oversight for critical decisions
        - Prevents autonomous errors in high-stakes scenarios
        - Provides safety net for uncertain situations
        - Enables graduated response based on severity
        - Supports compliance requirements
        - Facilitates learning from escalations
        - Maintains audit trail
    
    Trade-offs:
        - Reduces full autonomy
        - Introduces latency for escalated cases
        - Requires human availability
        - May create bottlenecks
        - Needs clear escalation criteria
        - Can interrupt workflow
    
    Production Considerations:
        - Define clear escalation criteria
        - Set appropriate confidence thresholds
        - Implement escalation routing rules
        - Ensure stakeholder availability
        - Track escalation metrics
        - Provide escalation status updates
        - Support escalation history
        - Enable escalation feedback
        - Monitor escalation patterns
        - Reduce false escalations
        - Support emergency escalations
        - Document escalation procedures
    """
    
    import os
    from typing import List, Dict, Any, Optional
    from datetime import datetime, timedelta
    from enum import Enum
    from dataclasses import dataclass, field
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class EscalationLevel(Enum):
        """Escalation severity levels."""
        CRITICAL = "critical"
        HIGH = "high"
        MEDIUM = "medium"
        LOW = "low"
    
    
    class EscalationStatus(Enum):
        """Status of escalation."""
        PENDING = "pending"
        IN_PROGRESS = "in_progress"
        RESOLVED = "resolved"
        CANCELLED = "cancelled"
    
    
    class EscalationTrigger(Enum):
        """Reasons for escalation."""
        LOW_CONFIDENCE = "low_confidence"
        POLICY_VIOLATION = "policy_violation"
        HIGH_RISK = "high_risk"
        SECURITY_INCIDENT = "security_incident"
        ERROR = "error"
        AMBIGUOUS = "ambiguous"
        SENSITIVE_DATA = "sensitive_data"
        MANUAL_REQUEST = "manual_request"
        THRESHOLD_EXCEEDED = "threshold_exceeded"
    
    
    @dataclass
    class Stakeholder:
        """Escalation stakeholder."""
        stakeholder_id: str
        name: str
        role: str
        email: str
        escalation_levels: List[EscalationLevel]
        availability: bool = True
        priority: int = 0
    
    
    @dataclass
    class EscalationCase:
        """Escalation case record."""
        case_id: str
        level: EscalationLevel
        trigger: EscalationTrigger
        title: str
        description: str
        context: Dict[str, Any]
        agent_id: str
        confidence_score: Optional[float]
        created_at: datetime
        assigned_to: Optional[str] = None
        status: EscalationStatus = EscalationStatus.PENDING
        resolution: Optional[str] = None
        resolved_at: Optional[datetime] = None
        metadata: Dict[str, Any] = field(default_factory=dict)
    
    
    @dataclass
    class EscalationRule:
        """Rule for triggering escalation."""
        rule_id: str
        name: str
        condition: str  # e.g., "confidence  None:
            """Add escalation stakeholder."""
            self.stakeholders[stakeholder.stakeholder_id] = stakeholder
            print(f"Added stakeholder: {stakeholder.name} ({stakeholder.role})")
        
        def add_rule(self, rule: EscalationRule) -> None:
            """Add escalation rule."""
            self.rules[rule.rule_id] = rule
            print(f"Added escalation rule: {rule.name}")
        
        def should_escalate(
            self,
            context: Dict[str, Any],
            confidence: Optional[float] = None
        ) -> tuple[bool, Optional[EscalationTrigger], Optional[EscalationLevel]]:
            """
            Determine if situation should be escalated.
            
            Returns:
                Tuple of (should_escalate, trigger, level)
            """
            # Check confidence threshold
            if confidence is not None and confidence  bool:
            """Evaluate if rule condition is met."""
            condition = rule.condition.lower()
            
            # Simple condition evaluation
            if "sensitive_data" in condition:
                return context.get("has_sensitive_data", False)
            
            if "high_risk" in condition:
                risk_score = context.get("risk_score", 0)
                return risk_score > self.risk_threshold
            
            if "error" in condition:
                return context.get("error_occurred", False)
            
            return False
        
        def create_escalation(
            self,
            title: str,
            description: str,
            context: Dict[str, Any],
            trigger: EscalationTrigger,
            level: Optional[EscalationLevel] = None,
            confidence: Optional[float] = None
        ) -> EscalationCase:
            """Create an escalation case."""
            # Assess severity if not provided
            if level is None:
                level = self._assess_severity(title, description, context, trigger)
            
            case = EscalationCase(
                case_id=f"esc_{len(self.cases) + 1}_{datetime.now().timestamp()}",
                level=level,
                trigger=trigger,
                title=title,
                description=description,
                context=context,
                agent_id=self.agent_id,
                confidence_score=confidence,
                created_at=datetime.now()
            )
            
            # Route to stakeholder
            stakeholder = self._route_escalation(case)
            if stakeholder:
                case.assigned_to = stakeholder.stakeholder_id
            
            self.cases.append(case)
            return case
        
        def _assess_severity(
            self,
            title: str,
            description: str,
            context: Dict[str, Any],
            trigger: EscalationTrigger
        ) -> EscalationLevel:
            """Assess severity using LLM."""
            try:
                result = self.severity_chain.invoke({
                    "title": title,
                    "description": description,
                    "context": str(context),
                    "trigger": trigger.value
                })
                
                # Parse severity
                for line in result.split('\n'):
                    if line.startswith("SEVERITY:"):
                        severity = line.replace("SEVERITY:", "").strip().lower()
                        if severity == "critical":
                            return EscalationLevel.CRITICAL
                        elif severity == "high":
                            return EscalationLevel.HIGH
                        elif severity == "medium":
                            return EscalationLevel.MEDIUM
                        else:
                            return EscalationLevel.LOW
                
                return EscalationLevel.MEDIUM
                
            except Exception as e:
                print(f"Error assessing severity: {e}")
                return EscalationLevel.MEDIUM
        
        def _route_escalation(
            self,
            case: EscalationCase
        ) -> Optional[Stakeholder]:
            """Route escalation to appropriate stakeholder."""
            # Find available stakeholders for this level
            candidates = [
                s for s in self.stakeholders.values()
                if case.level in s.escalation_levels and s.availability
            ]
            
            if not candidates:
                return None
            
            # Sort by priority and return highest
            candidates.sort(key=lambda s: s.priority, reverse=True)
            return candidates[0]
        
        def update_case_status(
            self,
            case_id: str,
            status: EscalationStatus,
            resolution: Optional[str] = None
        ) -> bool:
            """Update escalation case status."""
            case = next((c for c in self.cases if c.case_id == case_id), None)
            if not case:
                return False
            
            case.status = status
            if resolution:
                case.resolution = resolution
            
            if status == EscalationStatus.RESOLVED:
                case.resolved_at = datetime.now()
            
            return True
        
        def get_pending_escalations(
            self,
            level: Optional[EscalationLevel] = None,
            stakeholder_id: Optional[str] = None
        ) -> List[EscalationCase]:
            """Get pending escalation cases."""
            pending = [c for c in self.cases if c.status == EscalationStatus.PENDING]
            
            if level:
                pending = [c for c in pending if c.level == level]
            
            if stakeholder_id:
                pending = [c for c in pending if c.assigned_to == stakeholder_id]
            
            return pending
        
        def get_escalation_metrics(
            self,
            days: int = 7
        ) -> Dict[str, Any]:
            """Get escalation metrics."""
            cutoff = datetime.now() - timedelta(days=days)
            recent_cases = [c for c in self.cases if c.created_at >= cutoff]
            
            # Resolution time for resolved cases
            resolved = [c for c in recent_cases if c.status == EscalationStatus.RESOLVED]
            avg_resolution_time = None
            if resolved:
                times = [
                    (c.resolved_at - c.created_at).total_seconds() / 3600
                    for c in resolved if c.resolved_at
                ]
                avg_resolution_time = sum(times) / len(times) if times else None
            
            return {
                "period_days": days,
                "total_escalations": len(recent_cases),
                "pending": len([c for c in recent_cases if c.status == EscalationStatus.PENDING]),
                "in_progress": len([c for c in recent_cases if c.status == EscalationStatus.IN_PROGRESS]),
                "resolved": len(resolved),
                "by_level": {
                    level.value: len([c for c in recent_cases if c.level == level])
                    for level in EscalationLevel
                },
                "by_trigger": {
                    trigger.value: len([c for c in recent_cases if c.trigger == trigger])
                    for trigger in EscalationTrigger
                },
                "avg_resolution_hours": avg_resolution_time
            }
    
    
    def demonstrate_escalation():
        """Demonstrate the escalation pattern."""
        print("=" * 80)
        print("Escalation Pattern Demonstration")
        print("=" * 80)
        
        agent = EscalationAgent(agent_id="agent_001")
        
        # Demonstration 1: Add Stakeholders
        print("\n" + "=" * 80)
        print("Demonstration 1: Configure Escalation Stakeholders")
        print("=" * 80)
        
        support = Stakeholder(
            stakeholder_id="stake_001",
            name="Support Team",
            role="support",
            email="support@company.com",
            escalation_levels=[EscalationLevel.LOW, EscalationLevel.MEDIUM],
            priority=10
        )
        
        manager = Stakeholder(
            stakeholder_id="stake_002",
            name="Engineering Manager",
            role="manager",
            email="manager@company.com",
            escalation_levels=[EscalationLevel.MEDIUM, EscalationLevel.HIGH],
            priority=20
        )
        
        director = Stakeholder(
            stakeholder_id="stake_003",
            name="Director",
            role="director",
            email="director@company.com",
            escalation_levels=[EscalationLevel.HIGH, EscalationLevel.CRITICAL],
            priority=30
        )
        
        agent.add_stakeholder(support)
        agent.add_stakeholder(manager)
        agent.add_stakeholder(director)
        
        # Demonstration 2: Add Escalation Rules
        print("\n" + "=" * 80)
        print("Demonstration 2: Define Escalation Rules")
        print("=" * 80)
        
        sensitive_rule = EscalationRule(
            rule_id="rule_001",
            name="Sensitive Data Rule",
            condition="contains sensitive_data",
            level=EscalationLevel.HIGH,
            trigger=EscalationTrigger.SENSITIVE_DATA
        )
        
        risk_rule = EscalationRule(
            rule_id="rule_002",
            name="High Risk Rule",
            condition="high_risk",
            level=EscalationLevel.HIGH,
            trigger=EscalationTrigger.HIGH_RISK
        )
        
        agent.add_rule(sensitive_rule)
        agent.add_rule(risk_rule)
        
        # Demonstration 3: Low Confidence Escalation
        print("\n" + "=" * 80)
        print("Demonstration 3: Low Confidence Escalation")
        print("=" * 80)
        
        should_escalate, trigger, level = agent.should_escalate(
            context={"task": "medical_diagnosis"},
            confidence=0.45
        )
        
        print(f"Should escalate: {should_escalate}")
        print(f"Trigger: {trigger.value if trigger else None}")
        print(f"Level: {level.value if level else None}")
        
        if should_escalate:
            case1 = agent.create_escalation(
                title="Low Confidence Medical Diagnosis",
                description="Agent confidence below threshold for medical diagnosis",
                context={"task": "medical_diagnosis", "symptoms": "fever, cough"},
                trigger=trigger,
                level=level,
                confidence=0.45
            )
            print(f"\nCreated escalation case: {case1.case_id}")
            print(f"Assigned to: {case1.assigned_to}")
            print(f"Status: {case1.status.value}")
        
        # Demonstration 4: Security Incident Escalation
        print("\n" + "=" * 80)
        print("Demonstration 4: Security Incident Escalation")
        print("=" * 80)
        
        case2 = agent.create_escalation(
            title="Unauthorized Access Attempt",
            description="Multiple failed login attempts detected",
            context={
                "security_incident": True,
                "source_ip": "192.168.1.100",
                "attempts": 10
            },
            trigger=EscalationTrigger.SECURITY_INCIDENT,
            level=EscalationLevel.CRITICAL
        )
        
        print(f"Created critical escalation: {case2.case_id}")
        print(f"Level: {case2.level.value}")
        print(f"Trigger: {case2.trigger.value}")
        print(f"Assigned to: {case2.assigned_to}")
        
        # Demonstration 5: Rule-Based Escalation
        print("\n" + "=" * 80)
        print("Demonstration 5: Rule-Based Escalation")
        print("=" * 80)
        
        should_escalate, trigger, level = agent.should_escalate(
            context={
                "has_sensitive_data": True,
                "data_type": "PII"
            }
        )
        
        if should_escalate:
            case3 = agent.create_escalation(
                title="Sensitive Data Access",
                description="Request to access personally identifiable information",
                context={"has_sensitive_data": True, "data_type": "PII"},
                trigger=trigger,
                level=level
            )
            print(f"Created escalation: {case3.case_id}")
            print(f"Trigger: {trigger.value}")
            print(f"Level: {level.value}")
        
        # Demonstration 6: Manual Escalation Request
        print("\n" + "=" * 80)
        print("Demonstration 6: Manual Escalation Request")
        print("=" * 80)
        
        case4 = agent.create_escalation(
            title="Complex Customer Complaint",
            description="Customer requesting refund for premium service",
            context={
                "escalate": True,
                "customer_id": "cust_12345",
                "amount": 5000
            },
            trigger=EscalationTrigger.MANUAL_REQUEST
        )
        
        print(f"Manual escalation: {case4.case_id}")
        print(f"Level: {case4.level.value}")
        print(f"Assigned to: {case4.assigned_to}")
        
        # Demonstration 7: Case Resolution
        print("\n" + "=" * 80)
        print("Demonstration 7: Escalation Resolution")
        print("=" * 80)
        
        print(f"\nResolving case: {case3.case_id}")
        agent.update_case_status(
            case_id=case3.case_id,
            status=EscalationStatus.RESOLVED,
            resolution="Access granted with additional monitoring"
        )
        
        resolved_case = next(c for c in agent.cases if c.case_id == case3.case_id)
        print(f"Status: {resolved_case.status.value}")
        print(f"Resolution: {resolved_case.resolution}")
        
        # Demonstration 8: Pending Escalations
        print("\n" + "=" * 80)
        print("Demonstration 8: Pending Escalations")
        print("=" * 80)
        
        pending = agent.get_pending_escalations()
        print(f"\nTotal pending escalations: {len(pending)}")
        
        for case in pending:
            print(f"\n  Case: {case.case_id}")
            print(f"    Title: {case.title}")
            print(f"    Level: {case.level.value}")
            print(f"    Assigned to: {case.assigned_to}")
            print(f"    Age: {(datetime.now() - case.created_at).seconds // 60} minutes")
        
        # Demonstration 9: Critical Escalations Only
        print("\n" + "=" * 80)
        print("Demonstration 9: Critical Escalations")
        print("=" * 80)
        
        critical = agent.get_pending_escalations(level=EscalationLevel.CRITICAL)
        print(f"\nCritical pending escalations: {len(critical)}")
        for case in critical:
            print(f"  - {case.title}")
        
        # Demonstration 10: Escalation Metrics
        print("\n" + "=" * 80)
        print("Demonstration 10: Escalation Metrics")
        print("=" * 80)
        
        metrics = agent.get_escalation_metrics(days=7)
        print(f"\nEscalation Metrics (last {metrics['period_days']} days):")
        print(f"  Total Escalations: {metrics['total_escalations']}")
        print(f"  Pending: {metrics['pending']}")
        print(f"  In Progress: {metrics['in_progress']}")
        print(f"  Resolved: {metrics['resolved']}")
        print(f"\n  By Level:")
        for level, count in metrics['by_level'].items():
            if count > 0:
                print(f"    {level}: {count}")
        print(f"\n  By Trigger:")
        for trigger, count in metrics['by_trigger'].items():
            if count > 0:
                print(f"    {trigger}: {count}")
        
        if metrics['avg_resolution_hours']:
            print(f"\n  Avg Resolution Time: {metrics['avg_resolution_hours']:.1f} hours")
        
        # Summary
        print("\n" + "=" * 80)
        print("Summary: Escalation Pattern")
        print("=" * 80)
        print("""
    The Escalation Pattern ensures appropriate human oversight for critical situations:
    
    Key Features Demonstrated:
    1. Stakeholder Management - Configure escalation recipients by level
    2. Escalation Rules - Define automatic escalation triggers
    3. Confidence-Based Escalation - Escalate low-confidence decisions
    4. Security Escalation - Handle security incidents
    5. Rule-Based Escalation - Trigger based on context rules
    6. Manual Escalation - Support explicit escalation requests
    7. Case Resolution - Track escalation lifecycle
    8. Pending Cases - Monitor unresolved escalations
    9. Level Filtering - Focus on critical cases
    10. Metrics Tracking - Monitor escalation patterns
    
    Benefits:
    - Ensures human oversight for critical decisions
    - Prevents autonomous errors
    - Provides safety net for uncertainty
    - Graduated response by severity
    - Supports compliance
    - Facilitates learning
    - Maintains audit trail
    
    Best Practices:
    - Define clear escalation criteria
    - Set appropriate thresholds
    - Implement routing rules
    - Ensure stakeholder availability
    - Track metrics
    - Provide status updates
    - Support escalation history
    - Enable feedback loops
    - Monitor patterns
    - Reduce false escalations
    - Support emergency escalations
    - Document procedures
    
    This pattern is essential for safe AI systems requiring human oversight,
    especially in high-stakes domains like healthcare, finance, and security.
    """)
    
    
    if __name__ == "__main__":
        demonstrate_escalation()
    
        

    Agentic Design Pattern: Escalation

    Pattern 140: Escalation – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Escalation pattern implementation.


    Pattern Description

    Pattern 140: Escalation Pattern

    Description: The Escalation Pattern implements mechanisms for identifying situations that require human intervention or higher-level decision-making and routing them appropriately through an escalation hierarchy. This pattern recognizes when an agent encounters scenarios beyond its capabilities, authority, or confidence level and escalates to appropriate handlers based on severity and context.

    Escalation is critical for AI safety and reliability, ensuring that complex,
    high-stakes, or ambiguous situations receive appropriate human oversight. The
    pattern supports multiple escalation levels, severity assessment, automatic
    triggering based on rules or confidence thresholds, and routing to appropriate
    stakeholders. It balances agent autonomy with human control.
    
    This implementation provides a comprehensive escalation system with severity
    assessment, trigger conditions, escalation routing, stakeholder management,
    escalation tracking, and resolution workflows. It supports both rule-based
    and confidence-based escalation with customizable escalation paths.
    

    Components: – Severity Assessment: Evaluate situation severity – Trigger Detection: Identify when to escalate – Escalation Routing: Route to appropriate handler – Stakeholder Management: Manage escalation recipients – Escalation Tracking: Monitor escalation status – Resolution Workflow: Handle escalation lifecycle

    Use Cases: – High-stakes decisions (medical, financial, legal) – Low-confidence predictions – Policy violations – Security incidents – Customer complaints – System errors – Ethical dilemmas – Edge cases

    LangChain Implementation: This implementation uses: – LLM for severity assessment and decision complexity analysis – Rule-based escalation triggers – Confidence-threshold escalation – Hierarchical escalation routing – Escalation event tracking – Integration with human-in-the-loop systems

    Benefits: – Ensures human oversight for critical decisions – Prevents autonomous errors in high-stakes scenarios – Provides safety net for uncertain situations – Enables graduated response based on severity – Supports compliance requirements – Facilitates learning from escalations – Maintains audit trail

    Trade-offs: – Reduces full autonomy – Introduces latency for escalated cases – Requires human availability – May create bottlenecks – Needs clear escalation criteria – Can interrupt workflow

    Production Considerations: – Define clear escalation criteria – Set appropriate confidence thresholds – Implement escalation routing rules – Ensure stakeholder availability – Track escalation metrics – Provide escalation status updates – Support escalation history – Enable escalation feedback – Monitor escalation patterns – Reduce false escalations – Support emergency escalations – Document escalation procedures


    File Statistics

    • Total Lines: 709
    • Classes: 7
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 140: Escalation Pattern
    
    Description:
        The Escalation Pattern implements mechanisms for identifying situations that
        require human intervention or higher-level decision-making and routing them
        appropriately through an escalation hierarchy. This pattern recognizes when an
        agent encounters scenarios beyond its capabilities, authority, or confidence
        level and escalates to appropriate handlers based on severity and context.
    
        Escalation is critical for AI safety and reliability, ensuring that complex,
        high-stakes, or ambiguous situations receive appropriate human oversight. The
        pattern supports multiple escalation levels, severity assessment, automatic
        triggering based on rules or confidence thresholds, and routing to appropriate
        stakeholders. It balances agent autonomy with human control.
    
        This implementation provides a comprehensive escalation system with severity
        assessment, trigger conditions, escalation routing, stakeholder management,
        escalation tracking, and resolution workflows. It supports both rule-based
        and confidence-based escalation with customizable escalation paths.
    
    Components:
        - Severity Assessment: Evaluate situation severity
        - Trigger Detection: Identify when to escalate
        - Escalation Routing: Route to appropriate handler
        - Stakeholder Management: Manage escalation recipients
        - Escalation Tracking: Monitor escalation status
        - Resolution Workflow: Handle escalation lifecycle
    
    Use Cases:
        - High-stakes decisions (medical, financial, legal)
        - Low-confidence predictions
        - Policy violations
        - Security incidents
        - Customer complaints
        - System errors
        - Ethical dilemmas
        - Edge cases
    
    LangChain Implementation:
        This implementation uses:
        - LLM for severity assessment and decision complexity analysis
        - Rule-based escalation triggers
        - Confidence-threshold escalation
        - Hierarchical escalation routing
        - Escalation event tracking
        - Integration with human-in-the-loop systems
    
    Benefits:
        - Ensures human oversight for critical decisions
        - Prevents autonomous errors in high-stakes scenarios
        - Provides safety net for uncertain situations
        - Enables graduated response based on severity
        - Supports compliance requirements
        - Facilitates learning from escalations
        - Maintains audit trail
    
    Trade-offs:
        - Reduces full autonomy
        - Introduces latency for escalated cases
        - Requires human availability
        - May create bottlenecks
        - Needs clear escalation criteria
        - Can interrupt workflow
    
    Production Considerations:
        - Define clear escalation criteria
        - Set appropriate confidence thresholds
        - Implement escalation routing rules
        - Ensure stakeholder availability
        - Track escalation metrics
        - Provide escalation status updates
        - Support escalation history
        - Enable escalation feedback
        - Monitor escalation patterns
        - Reduce false escalations
        - Support emergency escalations
        - Document escalation procedures
    """
    

    Purpose: This module implements the Escalation pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import datetime.timedelta
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – datetime.timedelta: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: EscalationLevel

    Lines 95-100

    Inherits from: Enum

    Purpose:

    Escalation severity levels.
    

    Class: EscalationStatus

    Lines 103-108

    Inherits from: Enum

    Purpose:

    Status of escalation.
    

    Class: EscalationTrigger

    Lines 111-121

    Inherits from: Enum

    Purpose:

    Reasons for escalation.
    

    Class: Stakeholder

    Lines 125-133

    Purpose:

    Escalation stakeholder.
    

    Class: EscalationCase

    Lines 137-152

    Purpose:

    Escalation case record.
    

    Class: EscalationRule

    Lines 156-163

    Purpose:

    Rule for triggering escalation.
    

    Class: EscalationAgent

    Lines 166-432

    Purpose:

    Agent that manages escalation of decisions and situations.
    
    This agent identifies when to escalate, assesses severity,
    routes to appropriate stakeholders, and tracks resolution.
    

    Methods:

    __init__(self, agent_id, temperature)

    Lines 174-208

    Purpose:

    Initialize the escalation agent.
    

    Parameters: – agent_id: Agent id – temperature: Sampling temperature (0-1)

    add_stakeholder(self, stakeholder)

    Lines 210-213

    Purpose:

    Add escalation stakeholder.
    

    Parameters: – stakeholder: Stakeholder

    Returns: None

    add_rule(self, rule)

    Lines 215-218

    Purpose:

    Add escalation rule.
    

    Parameters: – rule: Rule

    Returns: None

    should_escalate(self, context, confidence)

    Lines 220-253

    Purpose:

    Determine if situation should be escalated.
    
    Returns:
        Tuple of (should_escalate, trigger, level)
    

    Parameters: – context: Context – confidence: Confidence

    Returns: <ast.Subscript object at 0x000001A06D649A90>

    _evaluate_rule(self, rule, context)

    Lines 255-274

    Purpose:

    Evaluate if rule condition is met.
    

    Parameters: – rule: Rule – context: Context

    Returns: bool

    create_escalation(self, title, description, context, trigger, level, confidence)

    Lines 276-308

    Purpose:

    Create an escalation case.
    

    Parameters: – title: Title – description: Description – context: Context – trigger: Trigger – level: Level – confidence: Confidence

    Returns: EscalationCase

    _assess_severity(self, title, description, context, trigger)

    Lines 310-343

    Purpose:

    Assess severity using LLM.
    

    Parameters: – title: Title – description: Description – context: Context – trigger: Trigger

    Returns: EscalationLevel

    _route_escalation(self, case)

    Lines 345-361

    Purpose:

    Route escalation to appropriate stakeholder.
    

    Parameters: – case: Case

    Returns: <ast.Subscript object at 0x000001A06D8890D0>

    update_case_status(self, case_id, status, resolution)

    Lines 363-381

    Purpose:

    Update escalation case status.
    

    Parameters: – case_id: Case id – status: Status – resolution: Resolution

    Returns: bool

    get_pending_escalations(self, level, stakeholder_id)

    Lines 383-397

    Purpose:

    Get pending escalation cases.
    

    Parameters: – level: Level – stakeholder_id: Stakeholder id

    Returns: <ast.Subscript object at 0x000001A06D824C90>

    get_escalation_metrics(self, days)

    Lines 399-432

    Purpose:

    Get escalation metrics.
    

    Parameters: – days: Days

    Returns: <ast.Subscript object at 0x000001A06D683110>


    Functions

    demonstrate_escalation()

    Lines 435-704

    Purpose:

    Demonstrate the escalation pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Escalation pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 139
    • Pattern 141

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Escalation pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 140_escalation.py
    Total Lines: 709
    Pattern Category: AI Agent Design Pattern #140


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Permission Authorization

    
        """
    Pattern 139: Permission & Authorization
    
    Description:
        The Permission & Authorization pattern implements fine-grained access control
        for agent systems, determining who can perform what actions on which resources.
        This pattern provides role-based access control (RBAC), attribute-based access
        control (ABAC), and resource-level permissions to ensure that agents and users
        only access what they're authorized to access.
    
        Authorization is fundamental to secure AI systems, especially in multi-user
        environments or when handling sensitive data. It enforces the principle of
        least privilege, prevents unauthorized access, and ensures compliance with
        security policies. The pattern supports hierarchical roles, permission
        inheritance, dynamic permissions, and context-aware authorization.
    
        This implementation provides a comprehensive authorization system with role
        management, permission assignment, access control checks, resource-level
        permissions, and permission delegation. It supports both static and dynamic
        authorization decisions based on user attributes, resource properties, and
        environmental context.
    
    Components:
        - Role Management: Define and manage user roles
        - Permission Assignment: Assign permissions to roles and users
        - Access Control: Check if action is authorized
        - Resource Protection: Control access to specific resources
        - Permission Delegation: Temporary permission grants
        - Context-Aware Authorization: Consider context in decisions
    
    Use Cases:
        - Multi-user AI systems
        - Enterprise agent platforms
        - Data access control
        - API authorization
        - Healthcare systems (HIPAA compliance)
        - Financial systems
        - Government systems
        - Multi-tenant platforms
    
    LangChain Implementation:
        This implementation uses:
        - Custom RBAC and ABAC systems
        - Permission hierarchy and inheritance
        - Resource-level access control
        - LLM for complex authorization decisions
        - Context-aware permission evaluation
        - Audit logging integration
    
    Benefits:
        - Enforces least privilege principle
        - Prevents unauthorized access
        - Supports compliance requirements
        - Enables fine-grained control
        - Facilitates security auditing
        - Supports multi-tenancy
        - Enables delegation
    
    Trade-offs:
        - Adds complexity to system
        - Requires permission management
        - May impact performance
        - Needs careful role design
        - Can be difficult to debug
        - Requires ongoing maintenance
    
    Production Considerations:
        - Design clear role hierarchy
        - Implement efficient permission checks
        - Cache authorization decisions
        - Log all authorization events
        - Support emergency access
        - Implement permission review process
        - Handle permission conflicts
        - Support temporal permissions
        - Provide audit capabilities
        - Test permission combinations
        - Document permission model
        - Monitor unauthorized attempts
    """
    
    import os
    from typing import List, Dict, Any, Optional, Set
    from datetime import datetime, timedelta
    from enum import Enum
    from dataclasses import dataclass, field
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class ActionType(Enum):
        """Types of actions."""
        READ = "read"
        WRITE = "write"
        UPDATE = "update"
        DELETE = "delete"
        EXECUTE = "execute"
        ADMIN = "admin"
        EXPORT = "export"
        SHARE = "share"
    
    
    class ResourceType(Enum):
        """Types of resources."""
        DATA = "data"
        MODEL = "model"
        AGENT = "agent"
        CONFIG = "config"
        USER = "user"
        API = "api"
    
    
    @dataclass
    class Permission:
        """Permission definition."""
        permission_id: str
        name: str
        description: str
        resource_type: ResourceType
        action: ActionType
        conditions: Dict[str, Any] = field(default_factory=dict)
        
        def __hash__(self):
            return hash(self.permission_id)
    
    
    @dataclass
    class Role:
        """Role definition."""
        role_id: str
        name: str
        description: str
        permissions: Set[Permission] = field(default_factory=set)
        parent_roles: Set[str] = field(default_factory=set)
        created_at: datetime = field(default_factory=datetime.now)
        
        def add_permission(self, permission: Permission):
            """Add permission to role."""
            self.permissions.add(permission)
        
        def remove_permission(self, permission: Permission):
            """Remove permission from role."""
            self.permissions.discard(permission)
        
        def has_permission(self, permission: Permission) -> bool:
            """Check if role has permission."""
            return permission in self.permissions
    
    
    @dataclass
    class User:
        """User definition."""
        user_id: str
        username: str
        roles: Set[str] = field(default_factory=set)
        direct_permissions: Set[Permission] = field(default_factory=set)
        attributes: Dict[str, Any] = field(default_factory=dict)
        created_at: datetime = field(default_factory=datetime.now)
        
        def add_role(self, role_id: str):
            """Add role to user."""
            self.roles.add(role_id)
        
        def remove_role(self, role_id: str):
            """Remove role from user."""
            self.roles.discard(role_id)
        
        def add_permission(self, permission: Permission):
            """Add direct permission to user."""
            self.direct_permissions.add(permission)
    
    
    @dataclass
    class Resource:
        """Resource definition."""
        resource_id: str
        resource_type: ResourceType
        owner_id: str
        attributes: Dict[str, Any] = field(default_factory=dict)
        created_at: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class AuthorizationRequest:
        """Authorization request."""
        user_id: str
        action: ActionType
        resource: Resource
        context: Dict[str, Any] = field(default_factory=dict)
    
    
    @dataclass
    class AuthorizationResult:
        """Authorization result."""
        authorized: bool
        reason: str
        matched_permissions: List[Permission]
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class PermissionAuthorizationAgent:
        """
        Agent that provides permission and authorization management.
        
        This agent manages roles, permissions, and authorization decisions
        using RBAC and ABAC approaches.
        """
        
        def __init__(self, temperature: float = 0.3):
            """Initialize the authorization agent."""
            self.llm = ChatOpenAI(temperature=temperature, model="gpt-3.5-turbo")
            self.roles: Dict[str, Role] = {}
            self.users: Dict[str, User] = {}
            self.resources: Dict[str, Resource] = {}
            self.permissions: Dict[str, Permission] = {}
            
            # Create authorization chain for complex decisions
            auth_prompt = ChatPromptTemplate.from_template(
                """You are an authorization expert. Determine if the user should be authorized for this action.
    
    User: {user_id}
    User Attributes: {user_attributes}
    Action: {action}
    Resource Type: {resource_type}
    Resource Attributes: {resource_attributes}
    Context: {context}
    
    Consider:
    1. User's roles and permissions
    2. Resource sensitivity
    3. Context (time, location, etc.)
    4. Business rules and policies
    
    Respond in this format:
    AUTHORIZED: yes/no
    REASON: explanation
    RISK_LEVEL: low/medium/high
    CONDITIONS: any conditions for authorization"""
            )
            self.auth_chain = auth_prompt | self.llm | StrOutputParser()
        
        def create_permission(
            self,
            permission_id: str,
            name: str,
            description: str,
            resource_type: ResourceType,
            action: ActionType,
            conditions: Optional[Dict[str, Any]] = None
        ) -> Permission:
            """Create a new permission."""
            permission = Permission(
                permission_id=permission_id,
                name=name,
                description=description,
                resource_type=resource_type,
                action=action,
                conditions=conditions or {}
            )
            self.permissions[permission_id] = permission
            return permission
        
        def create_role(
            self,
            role_id: str,
            name: str,
            description: str,
            parent_roles: Optional[Set[str]] = None
        ) -> Role:
            """Create a new role."""
            role = Role(
                role_id=role_id,
                name=name,
                description=description,
                parent_roles=parent_roles or set()
            )
            self.roles[role_id] = role
            return role
        
        def create_user(
            self,
            user_id: str,
            username: str,
            roles: Optional[Set[str]] = None,
            attributes: Optional[Dict[str, Any]] = None
        ) -> User:
            """Create a new user."""
            user = User(
                user_id=user_id,
                username=username,
                roles=roles or set(),
                attributes=attributes or {}
            )
            self.users[user_id] = user
            return user
        
        def create_resource(
            self,
            resource_id: str,
            resource_type: ResourceType,
            owner_id: str,
            attributes: Optional[Dict[str, Any]] = None
        ) -> Resource:
            """Create a new resource."""
            resource = Resource(
                resource_id=resource_id,
                resource_type=resource_type,
                owner_id=owner_id,
                attributes=attributes or {}
            )
            self.resources[resource_id] = resource
            return resource
        
        def assign_permission_to_role(
            self,
            role_id: str,
            permission_id: str
        ) -> bool:
            """Assign permission to role."""
            if role_id not in self.roles or permission_id not in self.permissions:
                return False
            
            role = self.roles[role_id]
            permission = self.permissions[permission_id]
            role.add_permission(permission)
            return True
        
        def assign_role_to_user(
            self,
            user_id: str,
            role_id: str
        ) -> bool:
            """Assign role to user."""
            if user_id not in self.users or role_id not in self.roles:
                return False
            
            user = self.users[user_id]
            user.add_role(role_id)
            return True
        
        def get_user_permissions(self, user_id: str) -> Set[Permission]:
            """Get all permissions for a user (from roles and direct)."""
            if user_id not in self.users:
                return set()
            
            user = self.users[user_id]
            permissions = user.direct_permissions.copy()
            
            # Add permissions from roles
            for role_id in user.roles:
                if role_id in self.roles:
                    role = self.roles[role_id]
                    permissions.update(role.permissions)
                    
                    # Add permissions from parent roles (inheritance)
                    for parent_id in role.parent_roles:
                        if parent_id in self.roles:
                            permissions.update(self.roles[parent_id].permissions)
            
            return permissions
        
        def check_authorization(
            self,
            request: AuthorizationRequest
        ) -> AuthorizationResult:
            """
            Check if user is authorized for action on resource.
            
            This performs both static (RBAC) and dynamic (ABAC) checks.
            """
            if request.user_id not in self.users:
                return AuthorizationResult(
                    authorized=False,
                    reason="User not found",
                    matched_permissions=[]
                )
            
            user = self.users[request.user_id]
            user_permissions = self.get_user_permissions(request.user_id)
            
            # Check if user is owner
            if request.resource.owner_id == request.user_id:
                return AuthorizationResult(
                    authorized=True,
                    reason="User is resource owner",
                    matched_permissions=[]
                )
            
            # Check static permissions (RBAC)
            matched = []
            for permission in user_permissions:
                if (permission.resource_type == request.resource.resource_type and
                    permission.action == request.action):
                    
                    # Check conditions
                    if self._check_conditions(permission.conditions, request.context):
                        matched.append(permission)
            
            if matched:
                return AuthorizationResult(
                    authorized=True,
                    reason=f"Authorized via permissions: {', '.join(p.name for p in matched)}",
                    matched_permissions=matched
                )
            
            # If no static match, use LLM for dynamic decision (ABAC)
            return self._dynamic_authorization(user, request)
        
        def _check_conditions(
            self,
            conditions: Dict[str, Any],
            context: Dict[str, Any]
        ) -> bool:
            """Check if conditions are met."""
            if not conditions:
                return True
            
            for key, value in conditions.items():
                if key not in context or context[key] != value:
                    return False
            
            return True
        
        def _dynamic_authorization(
            self,
            user: User,
            request: AuthorizationRequest
        ) -> AuthorizationResult:
            """Use LLM for dynamic authorization decision."""
            try:
                result = self.auth_chain.invoke({
                    "user_id": user.user_id,
                    "user_attributes": str(user.attributes),
                    "action": request.action.value,
                    "resource_type": request.resource.resource_type.value,
                    "resource_attributes": str(request.resource.attributes),
                    "context": str(request.context)
                })
                
                # Parse result
                authorized = "yes" in result.lower().split("AUTHORIZED:")[1].split("\n")[0]
                reason_line = [l for l in result.split("\n") if l.startswith("REASON:")]
                reason = reason_line[0].replace("REASON:", "").strip() if reason_line else "Dynamic authorization"
                
                return AuthorizationResult(
                    authorized=authorized,
                    reason=reason,
                    matched_permissions=[]
                )
                
            except Exception as e:
                return AuthorizationResult(
                    authorized=False,
                    reason=f"Authorization check failed: {e}",
                    matched_permissions=[]
                )
        
        def get_authorization_summary(self) -> Dict[str, Any]:
            """Get summary of authorization system."""
            return {
                "total_users": len(self.users),
                "total_roles": len(self.roles),
                "total_permissions": len(self.permissions),
                "total_resources": len(self.resources),
                "users_by_role": {
                    role_id: len([u for u in self.users.values() if role_id in u.roles])
                    for role_id in self.roles.keys()
                }
            }
    
    
    def demonstrate_permission_authorization():
        """Demonstrate the permission and authorization pattern."""
        print("=" * 80)
        print("Permission & Authorization Pattern Demonstration")
        print("=" * 80)
        
        agent = PermissionAuthorizationAgent()
        
        # Demonstration 1: Create Permissions
        print("\n" + "=" * 80)
        print("Demonstration 1: Create Permissions")
        print("=" * 80)
        
        read_data = agent.create_permission(
            permission_id="perm_read_data",
            name="Read Data",
            description="Permission to read data resources",
            resource_type=ResourceType.DATA,
            action=ActionType.READ
        )
        
        write_data = agent.create_permission(
            permission_id="perm_write_data",
            name="Write Data",
            description="Permission to write data resources",
            resource_type=ResourceType.DATA,
            action=ActionType.WRITE
        )
        
        admin_all = agent.create_permission(
            permission_id="perm_admin",
            name="Admin All",
            description="Full administrative access",
            resource_type=ResourceType.DATA,
            action=ActionType.ADMIN
        )
        
        print(f"Created permissions:")
        print(f"  - {read_data.name}: {read_data.description}")
        print(f"  - {write_data.name}: {write_data.description}")
        print(f"  - {admin_all.name}: {admin_all.description}")
        
        # Demonstration 2: Create Roles
        print("\n" + "=" * 80)
        print("Demonstration 2: Create Roles with Hierarchy")
        print("=" * 80)
        
        viewer_role = agent.create_role(
            role_id="role_viewer",
            name="Viewer",
            description="Can view data"
        )
        agent.assign_permission_to_role("role_viewer", "perm_read_data")
        
        editor_role = agent.create_role(
            role_id="role_editor",
            name="Editor",
            description="Can view and edit data",
            parent_roles={"role_viewer"}
        )
        agent.assign_permission_to_role("role_editor", "perm_write_data")
        
        admin_role = agent.create_role(
            role_id="role_admin",
            name="Admin",
            description="Full system access",
            parent_roles={"role_editor"}
        )
        agent.assign_permission_to_role("role_admin", "perm_admin")
        
        print(f"Created role hierarchy:")
        print(f"  Admin -> Editor -> Viewer")
        print(f"  - Viewer: {len(viewer_role.permissions)} permissions")
        print(f"  - Editor: {len(editor_role.permissions)} permissions (+ inherited)")
        print(f"  - Admin: {len(admin_role.permissions)} permissions (+ inherited)")
        
        # Demonstration 3: Create Users
        print("\n" + "=" * 80)
        print("Demonstration 3: Create Users with Roles")
        print("=" * 80)
        
        user1 = agent.create_user(
            user_id="user_001",
            username="alice",
            roles={"role_viewer"},
            attributes={"department": "sales", "level": "junior"}
        )
        
        user2 = agent.create_user(
            user_id="user_002",
            username="bob",
            roles={"role_editor"},
            attributes={"department": "engineering", "level": "senior"}
        )
        
        user3 = agent.create_user(
            user_id="user_003",
            username="charlie",
            roles={"role_admin"},
            attributes={"department": "it", "level": "manager"}
        )
        
        print(f"Created users:")
        print(f"  - {user1.username}: {user1.roles}")
        print(f"  - {user2.username}: {user2.roles}")
        print(f"  - {user3.username}: {user3.roles}")
        
        # Demonstration 4: Create Resources
        print("\n" + "=" * 80)
        print("Demonstration 4: Create Protected Resources")
        print("=" * 80)
        
        resource1 = agent.create_resource(
            resource_id="res_001",
            resource_type=ResourceType.DATA,
            owner_id="user_003",
            attributes={"classification": "public", "department": "sales"}
        )
        
        resource2 = agent.create_resource(
            resource_id="res_002",
            resource_type=ResourceType.DATA,
            owner_id="user_003",
            attributes={"classification": "confidential", "department": "finance"}
        )
        
        print(f"Created resources:")
        print(f"  - {resource1.resource_id}: {resource1.attributes['classification']}")
        print(f"  - {resource2.resource_id}: {resource2.attributes['classification']}")
        
        # Demonstration 5: Authorization Checks
        print("\n" + "=" * 80)
        print("Demonstration 5: Authorization Checks")
        print("=" * 80)
        
        # Alice (viewer) tries to read
        request1 = AuthorizationRequest(
            user_id="user_001",
            action=ActionType.READ,
            resource=resource1,
            context={}
        )
        result1 = agent.check_authorization(request1)
        print(f"\nAlice (viewer) reads public data:")
        print(f"  Authorized: {result1.authorized}")
        print(f"  Reason: {result1.reason}")
        
        # Alice tries to write
        request2 = AuthorizationRequest(
            user_id="user_001",
            action=ActionType.WRITE,
            resource=resource1,
            context={}
        )
        result2 = agent.check_authorization(request2)
        print(f"\nAlice (viewer) writes data:")
        print(f"  Authorized: {result2.authorized}")
        print(f"  Reason: {result2.reason}")
        
        # Bob (editor) tries to write
        request3 = AuthorizationRequest(
            user_id="user_002",
            action=ActionType.WRITE,
            resource=resource1,
            context={}
        )
        result3 = agent.check_authorization(request3)
        print(f"\nBob (editor) writes data:")
        print(f"  Authorized: {result3.authorized}")
        print(f"  Reason: {result3.reason}")
        
        # Demonstration 6: Owner Access
        print("\n" + "=" * 80)
        print("Demonstration 6: Resource Owner Access")
        print("=" * 80)
        
        # Charlie is owner
        request4 = AuthorizationRequest(
            user_id="user_003",
            action=ActionType.DELETE,
            resource=resource1,
            context={}
        )
        result4 = agent.check_authorization(request4)
        print(f"\nCharlie (owner) deletes resource:")
        print(f"  Authorized: {result4.authorized}")
        print(f"  Reason: {result4.reason}")
        
        # Demonstration 7: User Permissions Summary
        print("\n" + "=" * 80)
        print("Demonstration 7: User Permissions Summary")
        print("=" * 80)
        
        for user_id in ["user_001", "user_002", "user_003"]:
            user = agent.users[user_id]
            permissions = agent.get_user_permissions(user_id)
            print(f"\n{user.username} permissions:")
            print(f"  Roles: {', '.join(user.roles)}")
            print(f"  Total Permissions: {len(permissions)}")
            for perm in permissions:
                print(f"    - {perm.name}: {perm.action.value} {perm.resource_type.value}")
        
        # Demonstration 8: System Summary
        print("\n" + "=" * 80)
        print("Demonstration 8: Authorization System Summary")
        print("=" * 80)
        
        summary = agent.get_authorization_summary()
        print(f"\nAuthorization System:")
        print(f"  Users: {summary['total_users']}")
        print(f"  Roles: {summary['total_roles']}")
        print(f"  Permissions: {summary['total_permissions']}")
        print(f"  Resources: {summary['total_resources']}")
        print(f"\n  Users by Role:")
        for role, count in summary['users_by_role'].items():
            if count > 0:
                print(f"    {role}: {count}")
        
        # Summary
        print("\n" + "=" * 80)
        print("Summary: Permission & Authorization Pattern")
        print("=" * 80)
        print("""
    The Permission & Authorization pattern provides fine-grained access control:
    
    Key Features Demonstrated:
    1. Permission Management - Create and manage permissions
    2. Role-Based Access Control - RBAC with role hierarchy
    3. User Management - Assign roles and permissions to users
    4. Resource Protection - Control access to specific resources
    5. Authorization Checks - Verify user access rights
    6. Owner Access - Automatic authorization for resource owners
    7. Permission Inheritance - Inherit permissions from parent roles
    8. System Management - Track and manage authorization state
    
    Benefits:
    - Enforces least privilege
    - Prevents unauthorized access
    - Supports compliance
    - Enables fine-grained control
    - Facilitates auditing
    - Supports multi-tenancy
    - Enables role delegation
    
    Best Practices:
    - Design clear role hierarchy
    - Use principle of least privilege
    - Cache authorization decisions
    - Log authorization events
    - Support emergency access
    - Review permissions regularly
    - Handle permission conflicts
    - Test permission combinations
    - Document permission model
    - Monitor unauthorized attempts
    - Support temporal permissions
    - Provide audit capabilities
    
    This pattern is essential for secure multi-user AI systems requiring
    access control, compliance, and security enforcement.
    """)
    
    
    if __name__ == "__main__":
        demonstrate_permission_authorization()
    
        

    Agentic Design Pattern: Permission Authorization

    Pattern 139: Permission Authorization – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Permission Authorization pattern implementation.


    Pattern Description

    Pattern 139: Permission & Authorization

    Description: The Permission & Authorization pattern implements fine-grained access control for agent systems, determining who can perform what actions on which resources. This pattern provides role-based access control (RBAC), attribute-based access control (ABAC), and resource-level permissions to ensure that agents and users only access what they’re authorized to access.

    Authorization is fundamental to secure AI systems, especially in multi-user
    environments or when handling sensitive data. It enforces the principle of
    least privilege, prevents unauthorized access, and ensures compliance with
    security policies. The pattern supports hierarchical roles, permission
    inheritance, dynamic permissions, and context-aware authorization.
    
    This implementation provides a comprehensive authorization system with role
    management, permission assignment, access control checks, resource-level
    permissions, and permission delegation. It supports both static and dynamic
    authorization decisions based on user attributes, resource properties, and
    environmental context.
    

    Components: – Role Management: Define and manage user roles – Permission Assignment: Assign permissions to roles and users – Access Control: Check if action is authorized – Resource Protection: Control access to specific resources – Permission Delegation: Temporary permission grants – Context-Aware Authorization: Consider context in decisions

    Use Cases: – Multi-user AI systems – Enterprise agent platforms – Data access control – API authorization – Healthcare systems (HIPAA compliance) – Financial systems – Government systems – Multi-tenant platforms

    LangChain Implementation: This implementation uses: – Custom RBAC and ABAC systems – Permission hierarchy and inheritance – Resource-level access control – LLM for complex authorization decisions – Context-aware permission evaluation – Audit logging integration

    Benefits: – Enforces least privilege principle – Prevents unauthorized access – Supports compliance requirements – Enables fine-grained control – Facilitates security auditing – Supports multi-tenancy – Enables delegation

    Trade-offs: – Adds complexity to system – Requires permission management – May impact performance – Needs careful role design – Can be difficult to debug – Requires ongoing maintenance

    Production Considerations: – Design clear role hierarchy – Implement efficient permission checks – Cache authorization decisions – Log all authorization events – Support emergency access – Implement permission review process – Handle permission conflicts – Support temporal permissions – Provide audit capabilities – Test permission combinations – Document permission model – Monitor unauthorized attempts


    File Statistics

    • Total Lines: 742
    • Classes: 9
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 139: Permission & Authorization
    
    Description:
        The Permission & Authorization pattern implements fine-grained access control
        for agent systems, determining who can perform what actions on which resources.
        This pattern provides role-based access control (RBAC), attribute-based access
        control (ABAC), and resource-level permissions to ensure that agents and users
        only access what they're authorized to access.
    
        Authorization is fundamental to secure AI systems, especially in multi-user
        environments or when handling sensitive data. It enforces the principle of
        least privilege, prevents unauthorized access, and ensures compliance with
        security policies. The pattern supports hierarchical roles, permission
        inheritance, dynamic permissions, and context-aware authorization.
    
        This implementation provides a comprehensive authorization system with role
        management, permission assignment, access control checks, resource-level
        permissions, and permission delegation. It supports both static and dynamic
        authorization decisions based on user attributes, resource properties, and
        environmental context.
    
    Components:
        - Role Management: Define and manage user roles
        - Permission Assignment: Assign permissions to roles and users
        - Access Control: Check if action is authorized
        - Resource Protection: Control access to specific resources
        - Permission Delegation: Temporary permission grants
        - Context-Aware Authorization: Consider context in decisions
    
    Use Cases:
        - Multi-user AI systems
        - Enterprise agent platforms
        - Data access control
        - API authorization
        - Healthcare systems (HIPAA compliance)
        - Financial systems
        - Government systems
        - Multi-tenant platforms
    
    LangChain Implementation:
        This implementation uses:
        - Custom RBAC and ABAC systems
        - Permission hierarchy and inheritance
        - Resource-level access control
        - LLM for complex authorization decisions
        - Context-aware permission evaluation
        - Audit logging integration
    
    Benefits:
        - Enforces least privilege principle
        - Prevents unauthorized access
        - Supports compliance requirements
        - Enables fine-grained control
        - Facilitates security auditing
        - Supports multi-tenancy
        - Enables delegation
    
    Trade-offs:
        - Adds complexity to system
        - Requires permission management
        - May impact performance
        - Needs careful role design
        - Can be difficult to debug
        - Requires ongoing maintenance
    
    Production Considerations:
        - Design clear role hierarchy
        - Implement efficient permission checks
        - Cache authorization decisions
        - Log all authorization events
        - Support emergency access
        - Implement permission review process
        - Handle permission conflicts
        - Support temporal permissions
        - Provide audit capabilities
        - Test permission combinations
        - Document permission model
        - Monitor unauthorized attempts
    """
    

    Purpose: This module implements the Permission Authorization pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import datetime.timedelta
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    import typing.Set
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – datetime.timedelta: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Set: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: ActionType

    Lines 96-105

    Inherits from: Enum

    Purpose:

    Types of actions.
    

    Class: ResourceType

    Lines 108-115

    Inherits from: Enum

    Purpose:

    Types of resources.
    

    Class: Permission

    Lines 119-129

    Purpose:

    Permission definition.
    

    Methods:

    __hash__(self)

    Lines 128-129

    Purpose: Hash operation.

    Parameters:


    Class: Role

    Lines 133-152

    Purpose:

    Role definition.
    

    Methods:

    add_permission(self, permission)

    Lines 142-144

    Purpose:

    Add permission to role.
    

    Parameters: – permission: Permission

    remove_permission(self, permission)

    Lines 146-148

    Purpose:

    Remove permission from role.
    

    Parameters: – permission: Permission

    has_permission(self, permission)

    Lines 150-152

    Purpose:

    Check if role has permission.
    

    Parameters: – permission: Permission

    Returns: bool


    Class: User

    Lines 156-175

    Purpose:

    User definition.
    

    Methods:

    add_role(self, role_id)

    Lines 165-167

    Purpose:

    Add role to user.
    

    Parameters: – role_id: Role id

    remove_role(self, role_id)

    Lines 169-171

    Purpose:

    Remove role from user.
    

    Parameters: – role_id: Role id

    add_permission(self, permission)

    Lines 173-175

    Purpose:

    Add direct permission to user.
    

    Parameters: – permission: Permission


    Class: Resource

    Lines 179-185

    Purpose:

    Resource definition.
    

    Class: AuthorizationRequest

    Lines 189-194

    Purpose:

    Authorization request.
    

    Class: AuthorizationResult

    Lines 198-203

    Purpose:

    Authorization result.
    

    Class: PermissionAuthorizationAgent

    Lines 206-474

    Purpose:

    Agent that provides permission and authorization management.
    
    This agent manages roles, permissions, and authorization decisions
    using RBAC and ABAC approaches.
    

    Methods:

    __init__(self, temperature)

    Lines 214-245

    Purpose:

    Initialize the authorization agent.
    

    Parameters: – temperature: Sampling temperature (0-1)

    create_permission(self, permission_id, name, description, resource_type, action, conditions)

    Lines 247-266

    Purpose:

    Create a new permission.
    

    Parameters: – permission_id: Permission id – name: Name – description: Description – resource_type: Resource type – action: Action – conditions: Conditions

    Returns: Permission

    create_role(self, role_id, name, description, parent_roles)

    Lines 268-283

    Purpose:

    Create a new role.
    

    Parameters: – role_id: Role id – name: Name – description: Description – parent_roles: Parent roles

    Returns: Role

    create_user(self, user_id, username, roles, attributes)

    Lines 285-300

    Purpose:

    Create a new user.
    

    Parameters: – user_id: User id – username: Username – roles: Roles – attributes: Attributes

    Returns: User

    create_resource(self, resource_id, resource_type, owner_id, attributes)

    Lines 302-317

    Purpose:

    Create a new resource.
    

    Parameters: – resource_id: Resource id – resource_type: Resource type – owner_id: Owner id – attributes: Attributes

    Returns: Resource

    assign_permission_to_role(self, role_id, permission_id)

    Lines 319-331

    Purpose:

    Assign permission to role.
    

    Parameters: – role_id: Role id – permission_id: Permission id

    Returns: bool

    assign_role_to_user(self, user_id, role_id)

    Lines 333-344

    Purpose:

    Assign role to user.
    

    Parameters: – user_id: User id – role_id: Role id

    Returns: bool

    get_user_permissions(self, user_id)

    Lines 346-365

    Purpose:

    Get all permissions for a user (from roles and direct).
    

    Parameters: – user_id: User id

    Returns: <ast.Subscript object at 0x000001A06D70EE50>

    check_authorization(self, request)

    Lines 367-412

    Purpose:

    Check if user is authorized for action on resource.
    
    This performs both static (RBAC) and dynamic (ABAC) checks.
    

    Parameters: – request: Request

    Returns: AuthorizationResult

    _check_conditions(self, conditions, context)

    Lines 414-427

    Purpose:

    Check if conditions are met.
    

    Parameters: – conditions: Conditions – context: Context

    Returns: bool

    _dynamic_authorization(self, user, request)

    Lines 429-461

    Purpose:

    Use LLM for dynamic authorization decision.
    

    Parameters: – user: User – request: Request

    Returns: AuthorizationResult

    get_authorization_summary(self)

    Lines 463-474

    Purpose:

    Get summary of authorization system.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D7EDE90>


    Functions

    demonstrate_permission_authorization()

    Lines 477-737

    Purpose:

    Demonstrate the permission and authorization pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Permission Authorization pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 138
    • Pattern 140

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Permission Authorization pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 139_permission_authorization.py
    Total Lines: 742
    Pattern Category: AI Agent Design Pattern #139


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Audit Trail

    
        """
    Pattern 138: Audit Trail & Logging
    
    Description:
        The Audit Trail & Logging pattern provides comprehensive tracking and recording
        of all agent activities, decisions, and interactions. This pattern creates a
        complete, tamper-evident record of agent behavior that can be used for compliance,
        debugging, security analysis, and forensic investigation. It captures not just
        what happened, but why it happened, who was involved, and what data was accessed.
    
        Audit trails are critical for production AI systems, especially in regulated
        industries like healthcare, finance, and government. They provide accountability,
        enable incident investigation, support compliance audits, and help identify
        security threats. The pattern supports different log levels, structured logging,
        searchable records, and retention policies.
    
        This implementation provides a comprehensive audit system with activity logging,
        decision tracking, data access monitoring, security event recording, and forensic
        analysis capabilities. It supports multiple log formats, encryption, retention
        policies, and compliance reporting.
    
    Components:
        - Activity Logging: Records all agent actions
        - Decision Tracking: Captures reasoning and decisions
        - Data Access Monitoring: Tracks data read/write operations
        - Security Event Recording: Logs security-relevant events
        - Forensic Analysis: Tools for investigating incidents
        - Retention Management: Handles log retention and archival
    
    Use Cases:
        - Compliance auditing (SOX, HIPAA, GDPR)
        - Security incident investigation
        - Performance analysis and debugging
        - User behavior tracking
        - Regulatory reporting
        - Fraud detection
        - System monitoring
        - Forensic analysis
    
    LangChain Implementation:
        This implementation uses:
        - Custom audit logging system with structured records
        - Tamper-evident logging with checksums
        - LLM for log analysis and pattern detection
        - Structured audit events with rich metadata
        - Query capabilities for forensic analysis
        - Retention policies and archival
    
    Benefits:
        - Provides complete accountability
        - Enables incident investigation
        - Supports compliance requirements
        - Facilitates debugging and troubleshooting
        - Detects security threats
        - Creates audit trail for legal purposes
        - Enables behavior analysis
    
    Trade-offs:
        - Storage overhead for comprehensive logs
        - Performance impact from logging operations
        - Privacy concerns with detailed logging
        - Complexity in log management
        - Cost of log storage and retention
        - Potential information disclosure risks
    
    Production Considerations:
        - Use structured logging formats (JSON)
        - Implement log rotation and archival
        - Encrypt sensitive log data
        - Index logs for fast searching
        - Set appropriate retention periods
        - Monitor log storage usage
        - Implement log integrity verification
        - Provide audit reporting tools
        - Support log export and analysis
        - Handle PII data carefully
        - Implement access controls for logs
        - Consider regulatory requirements
    """
    
    import os
    import json
    import hashlib
    from typing import List, Dict, Any, Optional
    from datetime import datetime, timedelta
    from enum import Enum
    from dataclasses import dataclass, field, asdict
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class AuditEventType(Enum):
        """Types of audit events."""
        ACTION = "action"
        DECISION = "decision"
        DATA_ACCESS = "data_access"
        SECURITY = "security"
        ERROR = "error"
        CONFIGURATION = "configuration"
        AUTHENTICATION = "authentication"
        AUTHORIZATION = "authorization"
    
    
    class AuditLevel(Enum):
        """Audit log levels."""
        CRITICAL = "critical"
        HIGH = "high"
        MEDIUM = "medium"
        LOW = "low"
        INFO = "info"
    
    
    class DataOperation(Enum):
        """Types of data operations."""
        READ = "read"
        WRITE = "write"
        UPDATE = "update"
        DELETE = "delete"
        EXPORT = "export"
    
    
    @dataclass
    class AuditEvent:
        """Audit event record."""
        event_id: str
        event_type: AuditEventType
        level: AuditLevel
        timestamp: datetime
        agent_id: str
        user_id: Optional[str]
        action: str
        details: Dict[str, Any]
        result: Optional[str]
        duration_ms: Optional[float]
        metadata: Dict[str, Any] = field(default_factory=dict)
        checksum: Optional[str] = None
        
        def compute_checksum(self) -> str:
            """Compute checksum for tamper detection."""
            # Create canonical representation
            data = {
                "event_id": self.event_id,
                "event_type": self.event_type.value,
                "timestamp": self.timestamp.isoformat(),
                "agent_id": self.agent_id,
                "action": self.action,
                "details": json.dumps(self.details, sort_keys=True)
            }
            canonical = json.dumps(data, sort_keys=True)
            return hashlib.sha256(canonical.encode()).hexdigest()
        
        def to_dict(self) -> Dict[str, Any]:
            """Convert to dictionary."""
            d = asdict(self)
            d['event_type'] = self.event_type.value
            d['level'] = self.level.value
            d['timestamp'] = self.timestamp.isoformat()
            return d
    
    
    @dataclass
    class DataAccessEvent(AuditEvent):
        """Specialized event for data access."""
        data_type: str = ""
        operation: DataOperation = DataOperation.READ
        record_count: int = 0
        data_classification: str = "public"
    
    
    @dataclass
    class SecurityEvent(AuditEvent):
        """Specialized event for security incidents."""
        threat_level: str = "low"
        source_ip: Optional[str] = None
        attack_type: Optional[str] = None
    
    
    class AuditTrailAgent:
        """
        Agent that provides comprehensive audit trail and logging.
        
        This agent logs all activities, decisions, and events with rich
        metadata for compliance, security, and forensic analysis.
        """
        
        def __init__(self, agent_id: str, temperature: float = 0.3):
            """Initialize the audit trail agent."""
            self.agent_id = agent_id
            self.llm = ChatOpenAI(temperature=temperature, model="gpt-3.5-turbo")
            self.events: List[AuditEvent] = []
            self.retention_days = 90  # Default retention period
            
            # Create log analysis chain
            analysis_prompt = ChatPromptTemplate.from_template(
                """You are a log analysis expert. Analyze the following audit log events and identify patterns, anomalies, or security concerns.
    
    Events:
    {events}
    
    Provide analysis in this format:
    PATTERNS: List any patterns you observe
    ANOMALIES: List any unusual or suspicious activities
    SECURITY_CONCERNS: List any potential security issues
    RECOMMENDATIONS: Suggest actions to take"""
            )
            self.analysis_chain = analysis_prompt | self.llm | StrOutputParser()
        
        def log_event(
            self,
            event_type: AuditEventType,
            level: AuditLevel,
            action: str,
            details: Dict[str, Any],
            user_id: Optional[str] = None,
            result: Optional[str] = None,
            duration_ms: Optional[float] = None,
            metadata: Optional[Dict[str, Any]] = None
        ) -> AuditEvent:
            """Log an audit event."""
            event = AuditEvent(
                event_id=f"evt_{len(self.events) + 1}_{datetime.now().timestamp()}",
                event_type=event_type,
                level=level,
                timestamp=datetime.now(),
                agent_id=self.agent_id,
                user_id=user_id,
                action=action,
                details=details,
                result=result,
                duration_ms=duration_ms,
                metadata=metadata or {}
            )
            
            # Compute checksum for integrity
            event.checksum = event.compute_checksum()
            
            self.events.append(event)
            return event
        
        def log_data_access(
            self,
            operation: DataOperation,
            data_type: str,
            record_count: int,
            data_classification: str,
            user_id: Optional[str] = None,
            details: Optional[Dict[str, Any]] = None
        ) -> DataAccessEvent:
            """Log a data access event."""
            event = DataAccessEvent(
                event_id=f"data_{len(self.events) + 1}_{datetime.now().timestamp()}",
                event_type=AuditEventType.DATA_ACCESS,
                level=AuditLevel.MEDIUM if data_classification == "sensitive" else AuditLevel.LOW,
                timestamp=datetime.now(),
                agent_id=self.agent_id,
                user_id=user_id,
                action=f"{operation.value} {data_type}",
                details=details or {},
                result="success",
                duration_ms=None,
                data_type=data_type,
                operation=operation,
                record_count=record_count,
                data_classification=data_classification
            )
            
            event.checksum = event.compute_checksum()
            self.events.append(event)
            return event
        
        def log_security_event(
            self,
            action: str,
            threat_level: str,
            details: Dict[str, Any],
            source_ip: Optional[str] = None,
            attack_type: Optional[str] = None,
            user_id: Optional[str] = None
        ) -> SecurityEvent:
            """Log a security event."""
            level_map = {
                "critical": AuditLevel.CRITICAL,
                "high": AuditLevel.HIGH,
                "medium": AuditLevel.MEDIUM,
                "low": AuditLevel.LOW
            }
            
            event = SecurityEvent(
                event_id=f"sec_{len(self.events) + 1}_{datetime.now().timestamp()}",
                event_type=AuditEventType.SECURITY,
                level=level_map.get(threat_level, AuditLevel.MEDIUM),
                timestamp=datetime.now(),
                agent_id=self.agent_id,
                user_id=user_id,
                action=action,
                details=details,
                result="logged",
                duration_ms=None,
                threat_level=threat_level,
                source_ip=source_ip,
                attack_type=attack_type
            )
            
            event.checksum = event.compute_checksum()
            self.events.append(event)
            return event
        
        def query_events(
            self,
            event_type: Optional[AuditEventType] = None,
            level: Optional[AuditLevel] = None,
            user_id: Optional[str] = None,
            start_time: Optional[datetime] = None,
            end_time: Optional[datetime] = None,
            action_pattern: Optional[str] = None
        ) -> List[AuditEvent]:
            """Query audit events with filters."""
            filtered = self.events.copy()
            
            if event_type:
                filtered = [e for e in filtered if e.event_type == event_type]
            
            if level:
                filtered = [e for e in filtered if e.level == level]
            
            if user_id:
                filtered = [e for e in filtered if e.user_id == user_id]
            
            if start_time:
                filtered = [e for e in filtered if e.timestamp >= start_time]
            
            if end_time:
                filtered = [e for e in filtered if e.timestamp  str:
            """Analyze events for patterns and anomalies."""
            if events is None:
                # Analyze recent events
                cutoff = datetime.now() - timedelta(hours=time_window_hours)
                events = self.query_events(start_time=cutoff)
            
            if not events:
                return "No events to analyze"
            
            # Format events for analysis
            events_text = "\n".join([
                f"[{e.timestamp.isoformat()}] {e.event_type.value} - {e.action} "
                f"(level: {e.level.value}, user: {e.user_id or 'system'})"
                for e in events[-50:]  # Last 50 events
            ])
            
            try:
                analysis = self.analysis_chain.invoke({"events": events_text})
                return analysis
            except Exception as e:
                return f"Error analyzing events: {e}"
        
        def get_user_activity(
            self,
            user_id: str,
            hours: int = 24
        ) -> Dict[str, Any]:
            """Get activity summary for a user."""
            cutoff = datetime.now() - timedelta(hours=hours)
            events = self.query_events(user_id=user_id, start_time=cutoff)
            
            return {
                "user_id": user_id,
                "period_hours": hours,
                "total_events": len(events),
                "event_types": {
                    etype.value: len([e for e in events if e.event_type == etype])
                    for etype in AuditEventType
                },
                "actions": list(set(e.action for e in events)),
                "latest_activity": events[-1].timestamp if events else None
            }
        
        def get_security_summary(
            self,
            hours: int = 24
        ) -> Dict[str, Any]:
            """Get security events summary."""
            cutoff = datetime.now() - timedelta(hours=hours)
            security_events = self.query_events(
                event_type=AuditEventType.SECURITY,
                start_time=cutoff
            )
            
            return {
                "period_hours": hours,
                "total_security_events": len(security_events),
                "by_threat_level": {
                    level.value: len([
                        e for e in security_events 
                        if e.level == level
                    ])
                    for level in AuditLevel
                },
                "critical_events": len([
                    e for e in security_events 
                    if e.level == AuditLevel.CRITICAL
                ])
            }
        
        def verify_integrity(self) -> Dict[str, Any]:
            """Verify integrity of audit log."""
            total = len(self.events)
            verified = 0
            tampered = []
            
            for event in self.events:
                expected_checksum = event.compute_checksum()
                if event.checksum == expected_checksum:
                    verified += 1
                else:
                    tampered.append(event.event_id)
            
            return {
                "total_events": total,
                "verified": verified,
                "tampered": len(tampered),
                "tampered_event_ids": tampered,
                "integrity_score": verified / total if total > 0 else 1.0
            }
        
        def export_events(
            self,
            format: str = "json",
            events: Optional[List[AuditEvent]] = None
        ) -> str:
            """Export events to specified format."""
            events_to_export = events if events else self.events
            
            if format == "json":
                return json.dumps(
                    [e.to_dict() for e in events_to_export],
                    indent=2
                )
            elif format == "csv":
                # Simple CSV export
                lines = ["timestamp,event_type,level,agent_id,user_id,action,result"]
                for e in events_to_export:
                    lines.append(
                        f"{e.timestamp.isoformat()},{e.event_type.value},"
                        f"{e.level.value},{e.agent_id},{e.user_id or ''},"
                        f"{e.action},{e.result or ''}"
                    )
                return "\n".join(lines)
            else:
                return "Unsupported format"
        
        def apply_retention_policy(self) -> int:
            """Apply retention policy and remove old events."""
            cutoff = datetime.now() - timedelta(days=self.retention_days)
            original_count = len(self.events)
            
            self.events = [e for e in self.events if e.timestamp >= cutoff]
            
            removed = original_count - len(self.events)
            return removed
    
    
    def demonstrate_audit_trail():
        """Demonstrate the audit trail and logging pattern."""
        print("=" * 80)
        print("Audit Trail & Logging Pattern Demonstration")
        print("=" * 80)
        
        agent = AuditTrailAgent(agent_id="agent_001")
        
        # Demonstration 1: Basic Event Logging
        print("\n" + "=" * 80)
        print("Demonstration 1: Basic Event Logging")
        print("=" * 80)
        
        event = agent.log_event(
            event_type=AuditEventType.ACTION,
            level=AuditLevel.INFO,
            action="Process user request",
            details={"request_type": "query", "query": "What is the weather?"},
            user_id="user_123",
            result="success",
            duration_ms=150.5
        )
        
        print(f"\nLogged Event:")
        print(f"  ID: {event.event_id}")
        print(f"  Type: {event.event_type.value}")
        print(f"  Level: {event.level.value}")
        print(f"  Action: {event.action}")
        print(f"  User: {event.user_id}")
        print(f"  Checksum: {event.checksum[:16]}...")
        
        # Demonstration 2: Data Access Logging
        print("\n" + "=" * 80)
        print("Demonstration 2: Data Access Logging")
        print("=" * 80)
        
        data_event = agent.log_data_access(
            operation=DataOperation.READ,
            data_type="customer_records",
            record_count=150,
            data_classification="sensitive",
            user_id="analyst_456",
            details={"query": "SELECT * FROM customers WHERE region='EU'"}
        )
        
        print(f"\nData Access Event:")
        print(f"  Operation: {data_event.operation.value}")
        print(f"  Data Type: {data_event.data_type}")
        print(f"  Records: {data_event.record_count}")
        print(f"  Classification: {data_event.data_classification}")
        print(f"  Level: {data_event.level.value}")
        
        # Demonstration 3: Security Event Logging
        print("\n" + "=" * 80)
        print("Demonstration 3: Security Event Logging")
        print("=" * 80)
        
        security_event = agent.log_security_event(
            action="Failed authentication attempt",
            threat_level="medium",
            details={"reason": "invalid_credentials", "attempts": 3},
            source_ip="192.168.1.100",
            attack_type="brute_force",
            user_id="unknown"
        )
        
        print(f"\nSecurity Event:")
        print(f"  Action: {security_event.action}")
        print(f"  Threat Level: {security_event.threat_level}")
        print(f"  Attack Type: {security_event.attack_type}")
        print(f"  Source IP: {security_event.source_ip}")
        print(f"  Level: {security_event.level.value}")
        
        # Log more events for testing
        agent.log_event(
            event_type=AuditEventType.DECISION,
            level=AuditLevel.MEDIUM,
            action="Route to specialist agent",
            details={"specialist": "medical", "confidence": 0.85},
            user_id="user_123"
        )
        
        agent.log_data_access(
            operation=DataOperation.WRITE,
            data_type="transaction_logs",
            record_count=1,
            data_classification="confidential",
            user_id="system"
        )
        
        # Demonstration 4: Query Events
        print("\n" + "=" * 80)
        print("Demonstration 4: Query Events")
        print("=" * 80)
        
        security_events = agent.query_events(event_type=AuditEventType.SECURITY)
        print(f"\nSecurity Events: {len(security_events)}")
        
        user_events = agent.query_events(user_id="user_123")
        print(f"Events by user_123: {len(user_events)}")
        
        data_events = agent.query_events(event_type=AuditEventType.DATA_ACCESS)
        print(f"Data Access Events: {len(data_events)}")
        
        # Demonstration 5: User Activity Summary
        print("\n" + "=" * 80)
        print("Demonstration 5: User Activity Summary")
        print("=" * 80)
        
        activity = agent.get_user_activity("user_123")
        print(f"\nUser Activity Summary:")
        print(f"  User: {activity['user_id']}")
        print(f"  Period: {activity['period_hours']} hours")
        print(f"  Total Events: {activity['total_events']}")
        print(f"  Actions: {', '.join(activity['actions'])}")
        
        # Demonstration 6: Security Summary
        print("\n" + "=" * 80)
        print("Demonstration 6: Security Summary")
        print("=" * 80)
        
        sec_summary = agent.get_security_summary()
        print(f"\nSecurity Summary:")
        print(f"  Period: {sec_summary['period_hours']} hours")
        print(f"  Total Security Events: {sec_summary['total_security_events']}")
        print(f"  Critical Events: {sec_summary['critical_events']}")
        print(f"  By Threat Level:")
        for level, count in sec_summary['by_threat_level'].items():
            if count > 0:
                print(f"    {level}: {count}")
        
        # Demonstration 7: Integrity Verification
        print("\n" + "=" * 80)
        print("Demonstration 7: Integrity Verification")
        print("=" * 80)
        
        integrity = agent.verify_integrity()
        print(f"\nIntegrity Check:")
        print(f"  Total Events: {integrity['total_events']}")
        print(f"  Verified: {integrity['verified']}")
        print(f"  Tampered: {integrity['tampered']}")
        print(f"  Integrity Score: {integrity['integrity_score']:.2%}")
        
        # Demonstration 8: Export Events
        print("\n" + "=" * 80)
        print("Demonstration 8: Export Events")
        print("=" * 80)
        
        # Export as JSON (first 2 events)
        json_export = agent.export_events(format="json", events=agent.events[:2])
        print(f"\nJSON Export (sample):")
        print(json_export[:300] + "...")
        
        # Export as CSV
        csv_export = agent.export_events(format="csv", events=agent.events[:3])
        print(f"\nCSV Export (sample):")
        print("\n".join(csv_export.split("\n")[:4]))
        
        # Summary
        print("\n" + "=" * 80)
        print("Summary: Audit Trail & Logging Pattern")
        print("=" * 80)
        print(f"""
    The Audit Trail & Logging pattern provides comprehensive activity tracking:
    
    Key Features Demonstrated:
    1. Event Logging - Structured audit events with rich metadata
    2. Data Access Tracking - Specialized logging for data operations
    3. Security Events - Track security incidents and threats
    4. Query Capabilities - Filter and search audit logs
    5. User Activity - Track and analyze user behavior
    6. Security Monitoring - Monitor security events
    7. Integrity Verification - Tamper-evident logging with checksums
    8. Export Functionality - Export logs in multiple formats
    
    Current State:
    - Total Events: {len(agent.events)}
    - Event Types: {len(set(e.event_type for e in agent.events))}
    - Users: {len(set(e.user_id for e in agent.events if e.user_id))}
    - Integrity Score: {integrity['integrity_score']:.2%}
    
    Benefits:
    - Complete accountability and traceability
    - Enables incident investigation
    - Supports compliance requirements
    - Facilitates debugging
    - Detects security threats
    - Provides audit trail for legal purposes
    
    Best Practices:
    - Use structured logging (JSON)
    - Include rich metadata in events
    - Implement tamper detection
    - Set appropriate retention periods
    - Encrypt sensitive log data
    - Index logs for searching
    - Monitor log storage
    - Provide query capabilities
    - Support compliance reporting
    - Handle PII data carefully
    
    This pattern is essential for production AI systems requiring compliance,
    security monitoring, and forensic investigation capabilities.
    """)
    
    
    if __name__ == "__main__":
        demonstrate_audit_trail()
    
        

    Agentic Design Pattern: Audit Trail

    Pattern 138: Audit Trail – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Audit Trail pattern implementation.


    Pattern Description

    Pattern 138: Audit Trail & Logging

    Description: The Audit Trail & Logging pattern provides comprehensive tracking and recording of all agent activities, decisions, and interactions. This pattern creates a complete, tamper-evident record of agent behavior that can be used for compliance, debugging, security analysis, and forensic investigation. It captures not just what happened, but why it happened, who was involved, and what data was accessed.

    Audit trails are critical for production AI systems, especially in regulated
    industries like healthcare, finance, and government. They provide accountability,
    enable incident investigation, support compliance audits, and help identify
    security threats. The pattern supports different log levels, structured logging,
    searchable records, and retention policies.
    
    This implementation provides a comprehensive audit system with activity logging,
    decision tracking, data access monitoring, security event recording, and forensic
    analysis capabilities. It supports multiple log formats, encryption, retention
    policies, and compliance reporting.
    

    Components: – Activity Logging: Records all agent actions – Decision Tracking: Captures reasoning and decisions – Data Access Monitoring: Tracks data read/write operations – Security Event Recording: Logs security-relevant events – Forensic Analysis: Tools for investigating incidents – Retention Management: Handles log retention and archival

    Use Cases: – Compliance auditing (SOX, HIPAA, GDPR) – Security incident investigation – Performance analysis and debugging – User behavior tracking – Regulatory reporting – Fraud detection – System monitoring – Forensic analysis

    LangChain Implementation: This implementation uses: – Custom audit logging system with structured records – Tamper-evident logging with checksums – LLM for log analysis and pattern detection – Structured audit events with rich metadata – Query capabilities for forensic analysis – Retention policies and archival

    Benefits: – Provides complete accountability – Enables incident investigation – Supports compliance requirements – Facilitates debugging and troubleshooting – Detects security threats – Creates audit trail for legal purposes – Enables behavior analysis

    Trade-offs: – Storage overhead for comprehensive logs – Performance impact from logging operations – Privacy concerns with detailed logging – Complexity in log management – Cost of log storage and retention – Potential information disclosure risks

    Production Considerations: – Use structured logging formats (JSON) – Implement log rotation and archival – Encrypt sensitive log data – Index logs for fast searching – Set appropriate retention periods – Monitor log storage usage – Implement log integrity verification – Provide audit reporting tools – Support log export and analysis – Handle PII data carefully – Implement access controls for logs – Consider regulatory requirements


    File Statistics

    • Total Lines: 686
    • Classes: 7
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 138: Audit Trail & Logging
    
    Description:
        The Audit Trail & Logging pattern provides comprehensive tracking and recording
        of all agent activities, decisions, and interactions. This pattern creates a
        complete, tamper-evident record of agent behavior that can be used for compliance,
        debugging, security analysis, and forensic investigation. It captures not just
        what happened, but why it happened, who was involved, and what data was accessed.
    
        Audit trails are critical for production AI systems, especially in regulated
        industries like healthcare, finance, and government. They provide accountability,
        enable incident investigation, support compliance audits, and help identify
        security threats. The pattern supports different log levels, structured logging,
        searchable records, and retention policies.
    
        This implementation provides a comprehensive audit system with activity logging,
        decision tracking, data access monitoring, security event recording, and forensic
        analysis capabilities. It supports multiple log formats, encryption, retention
        policies, and compliance reporting.
    
    Components:
        - Activity Logging: Records all agent actions
        - Decision Tracking: Captures reasoning and decisions
        - Data Access Monitoring: Tracks data read/write operations
        - Security Event Recording: Logs security-relevant events
        - Forensic Analysis: Tools for investigating incidents
        - Retention Management: Handles log retention and archival
    
    Use Cases:
        - Compliance auditing (SOX, HIPAA, GDPR)
        - Security incident investigation
        - Performance analysis and debugging
        - User behavior tracking
        - Regulatory reporting
        - Fraud detection
        - System monitoring
        - Forensic analysis
    
    LangChain Implementation:
        This implementation uses:
        - Custom audit logging system with structured records
        - Tamper-evident logging with checksums
        - LLM for log analysis and pattern detection
        - Structured audit events with rich metadata
        - Query capabilities for forensic analysis
        - Retention policies and archival
    
    Benefits:
        - Provides complete accountability
        - Enables incident investigation
        - Supports compliance requirements
        - Facilitates debugging and troubleshooting
        - Detects security threats
        - Creates audit trail for legal purposes
        - Enables behavior analysis
    
    Trade-offs:
        - Storage overhead for comprehensive logs
        - Performance impact from logging operations
        - Privacy concerns with detailed logging
        - Complexity in log management
        - Cost of log storage and retention
        - Potential information disclosure risks
    
    Production Considerations:
        - Use structured logging formats (JSON)
        - Implement log rotation and archival
        - Encrypt sensitive log data
        - Index logs for fast searching
        - Set appropriate retention periods
        - Monitor log storage usage
        - Implement log integrity verification
        - Provide audit reporting tools
        - Support log export and analysis
        - Handle PII data carefully
        - Implement access controls for logs
        - Consider regulatory requirements
    """
    

    Purpose: This module implements the Audit Trail pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.asdict
    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import datetime.timedelta
    import enum.Enum
    import json
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    

    Purpose: Core Python functionality: – dataclasses.asdict: Simplified class definitions with @dataclass – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – datetime.timedelta: Date and time handling – enum.Enum: Enumeration support – json: JSON serialization/deserialization – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    from hashlib
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: AuditEventType

    Lines 97-106

    Inherits from: Enum

    Purpose:

    Types of audit events.
    

    Class: AuditLevel

    Lines 109-115

    Inherits from: Enum

    Purpose:

    Audit log levels.
    

    Class: DataOperation

    Lines 118-124

    Inherits from: Enum

    Purpose:

    Types of data operations.
    

    Class: AuditEvent

    Lines 128-163

    Purpose:

    Audit event record.
    

    Methods:

    compute_checksum(self)

    Lines 143-155

    Purpose:

    Compute checksum for tamper detection.
    

    Parameters:

    Returns: str

    to_dict(self)

    Lines 157-163

    Purpose:

    Convert to dictionary.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D856750>


    Class: DataAccessEvent

    Lines 167-172

    Inherits from: AuditEvent

    Purpose:

    Specialized event for data access.
    

    Class: SecurityEvent

    Lines 176-180

    Inherits from: AuditEvent

    Purpose:

    Specialized event for security incidents.
    

    Class: AuditTrailAgent

    Lines 183-475

    Purpose:

    Agent that provides comprehensive audit trail and logging.
    
    This agent logs all activities, decisions, and events with rich
    metadata for compliance, security, and forensic analysis.
    

    Methods:

    __init__(self, agent_id, temperature)

    Lines 191-211

    Purpose:

    Initialize the audit trail agent.
    

    Parameters: – agent_id: Agent id – temperature: Sampling temperature (0-1)

    log_event(self, event_type, level, action, details, user_id, result, duration_ms, metadata)

    Lines 213-243

    Purpose:

    Log an audit event.
    

    Parameters: – event_type: Event type – level: Level – action: Action – details: Details – user_id: User id – result: Result – duration_ms: Duration ms – metadata: Metadata

    Returns: AuditEvent

    log_data_access(self, operation, data_type, record_count, data_classification, user_id, details)

    Lines 245-274

    Purpose:

    Log a data access event.
    

    Parameters: – operation: Operation – data_type: Data type – record_count: Record count – data_classification: Data classification – user_id: User id – details: Details

    Returns: DataAccessEvent

    log_security_event(self, action, threat_level, details, source_ip, attack_type, user_id)

    Lines 276-311

    Purpose:

    Log a security event.
    

    Parameters: – action: Action – threat_level: Threat level – details: Details – source_ip: Source ip – attack_type: Attack type – user_id: User id

    Returns: SecurityEvent

    query_events(self, event_type, level, user_id, start_time, end_time, action_pattern)

    Lines 313-343

    Purpose:

    Query audit events with filters.
    

    Parameters: – event_type: Event type – level: Level – user_id: User id – start_time: Start time – end_time: End time – action_pattern: Action pattern

    Returns: <ast.Subscript object at 0x000001A06D629ED0>

    analyze_events(self, events, time_window_hours)

    Lines 345-370

    Purpose:

    Analyze events for patterns and anomalies.
    

    Parameters: – events: Events – time_window_hours: Time window hours

    Returns: str

    get_user_activity(self, user_id, hours)

    Lines 372-391

    Purpose:

    Get activity summary for a user.
    

    Parameters: – user_id: User id – hours: Hours

    Returns: <ast.Subscript object at 0x000001A06D7E5C90>

    get_security_summary(self, hours)

    Lines 393-418

    Purpose:

    Get security events summary.
    

    Parameters: – hours: Hours

    Returns: <ast.Subscript object at 0x000001A06D824AD0>

    verify_integrity(self)

    Lines 420-439

    Purpose:

    Verify integrity of audit log.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D659BD0>

    export_events(self, format, events)

    Lines 441-465

    Purpose:

    Export events to specified format.
    

    Parameters: – format: Format – events: Events

    Returns: str

    apply_retention_policy(self)

    Lines 467-475

    Purpose:

    Apply retention policy and remove old events.
    

    Parameters:

    Returns: int


    Functions

    demonstrate_audit_trail()

    Lines 478-681

    Purpose:

    Demonstrate the audit trail and logging pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Audit Trail pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 137
    • Pattern 139

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Audit Trail pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 138_audit_trail.py
    Total Lines: 686
    Pattern Category: AI Agent Design Pattern #138


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Policy Based Control

    
        """
    Pattern 137: Policy-Based Control
    
    Description:
        The Policy-Based Control pattern implements governance mechanisms that enforce
        organizational policies, regulatory requirements, and operational constraints on
        agent behavior. This pattern provides a framework for defining, validating, and
        enforcing policies that control what actions agents can take, what data they can
        access, and how they should behave in various contexts.
    
        Policy-based control is essential for production deployments where agents must
        operate within well-defined boundaries. It enables organizations to maintain
        compliance with regulations, enforce security policies, implement business rules,
        and ensure ethical AI behavior. The pattern supports both hard constraints (must
        be followed) and soft constraints (should be followed with exceptions).
    
        This implementation provides a comprehensive policy management system with rule
        definition, policy validation, violation detection, enforcement mechanisms, and
        policy composition. It supports multiple policy types including security policies,
        data policies, behavioral policies, and resource policies, with the ability to
        combine policies and handle conflicts.
    
    Components:
        - Policy Definition: Structured rules with conditions and actions
        - Policy Validation: Checks if actions comply with policies
        - Violation Detection: Identifies policy breaches
        - Enforcement Mechanisms: Blocks, modifies, or logs violations
        - Policy Composition: Combines multiple policies
        - Conflict Resolution: Handles policy conflicts
    
    Use Cases:
        - Regulatory compliance (GDPR, HIPAA, SOC2)
        - Security policy enforcement
        - Business rule implementation
        - Ethical AI constraints
        - Resource usage governance
        - Data access control
        - Content moderation
        - Operational safety
    
    LangChain Implementation:
        This implementation uses:
        - ChatOpenAI for policy validation and interpretation
        - Custom policy engine for rule enforcement
        - Structured policy definitions with conditions and actions
        - LLM-based policy reasoning for complex scenarios
        - Policy composition and inheritance mechanisms
        - Violation tracking and audit logging
    
    Benefits:
        - Ensures compliance with regulations and standards
        - Enforces organizational policies consistently
        - Provides audit trail for policy enforcement
        - Reduces risk of policy violations
        - Enables fine-grained control over agent behavior
        - Supports policy versioning and evolution
        - Facilitates policy management at scale
    
    Trade-offs:
        - May restrict agent flexibility and autonomy
        - Can increase latency due to policy checks
        - Requires careful policy design to avoid conflicts
        - May need ongoing policy maintenance
        - Can create complexity in policy management
        - Requires balance between control and capability
    
    Production Considerations:
        - Design clear, unambiguous policies
        - Implement efficient policy evaluation
        - Cache policy decisions when possible
        - Log all policy violations with context
        - Support policy testing and simulation
        - Implement policy versioning
        - Provide policy override mechanisms
        - Monitor policy effectiveness
        - Support policy composition
        - Handle policy conflicts gracefully
        - Implement emergency policy updates
        - Provide policy documentation
    """
    
    import os
    from typing import List, Dict, Any, Optional, Set, Tuple
    from datetime import datetime
    from enum import Enum
    from dataclasses import dataclass, field
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class PolicyType(Enum):
        """Types of policies."""
        SECURITY = "security"
        DATA = "data"
        BEHAVIORAL = "behavioral"
        RESOURCE = "resource"
        COMPLIANCE = "compliance"
        ETHICAL = "ethical"
        OPERATIONAL = "operational"
        CONTENT = "content"
    
    
    class PolicySeverity(Enum):
        """Severity levels for policy violations."""
        CRITICAL = "critical"
        HIGH = "high"
        MEDIUM = "medium"
        LOW = "low"
        INFO = "info"
    
    
    class EnforcementAction(Enum):
        """Actions to take when policy is violated."""
        BLOCK = "block"
        MODIFY = "modify"
        LOG = "log"
        WARN = "warn"
        ESCALATE = "escalate"
        ALLOW = "allow"
    
    
    @dataclass
    class PolicyCondition:
        """Condition for policy rule."""
        field: str
        operator: str  # eq, ne, gt, lt, contains, matches, etc.
        value: Any
        
        def evaluate(self, context: Dict[str, Any]) -> bool:
            """Evaluate condition against context."""
            if self.field not in context:
                return False
            
            field_value = context[self.field]
            
            if self.operator == "eq":
                return field_value == self.value
            elif self.operator == "ne":
                return field_value != self.value
            elif self.operator == "gt":
                return field_value > self.value
            elif self.operator == "lt":
                return field_value = self.value
            elif self.operator == "lte":
                return field_value  None:
            """Add a policy to the system."""
            self.policies[policy.policy_id] = policy
            print(f"Added policy: {policy.name} (ID: {policy.policy_id})")
        
        def remove_policy(self, policy_id: str) -> None:
            """Remove a policy from the system."""
            if policy_id in self.policies:
                policy = self.policies.pop(policy_id)
                print(f"Removed policy: {policy.name}")
            else:
                print(f"Policy not found: {policy_id}")
        
        def enable_policy(self, policy_id: str) -> None:
            """Enable a policy."""
            if policy_id in self.policies:
                self.policies[policy_id].enabled = True
                print(f"Enabled policy: {self.policies[policy_id].name}")
        
        def disable_policy(self, policy_id: str) -> None:
            """Disable a policy."""
            if policy_id in self.policies:
                self.policies[policy_id].enabled = False
                print(f"Disabled policy: {self.policies[policy_id].name}")
        
        def validate_action(
            self,
            action: str,
            context: Dict[str, Any]
        ) -> Tuple[bool, List[PolicyViolation]]:
            """
            Validate an action against all applicable policies.
            
            Returns:
                Tuple of (is_valid, list of violations)
            """
            violations = []
            
            # Get applicable policies (enabled, sorted by priority)
            applicable_policies = sorted(
                [p for p in self.policies.values() if p.enabled],
                key=lambda p: p.priority,
                reverse=True
            )
            
            for policy in applicable_policies:
                # Check if policy conditions match
                if self._conditions_match(policy.conditions, context):
                    # Use LLM for detailed validation
                    violation = self._check_policy_violation(policy, action, context)
                    if violation:
                        violations.append(violation)
                        self.violations.append(violation)
            
            is_valid = len(violations) == 0
            return is_valid, violations
        
        def _conditions_match(
            self,
            conditions: List[PolicyCondition],
            context: Dict[str, Any]
        ) -> bool:
            """Check if all conditions match the context."""
            if not conditions:
                return True  # No conditions means always applicable
            
            return all(condition.evaluate(context) for condition in conditions)
        
        def _check_policy_violation(
            self,
            policy: Policy,
            action: str,
            context: Dict[str, Any]
        ) -> Optional[PolicyViolation]:
            """Check if action violates policy using LLM."""
            try:
                result = self.validation_chain.invoke({
                    "policy_name": policy.name,
                    "policy_description": policy.description,
                    "policy_type": policy.policy_type.value,
                    "severity": policy.severity.value,
                    "action": action,
                    "context": str(context)
                })
                
                # Parse result
                lines = result.strip().split('\n')
                violates = False
                reason = ""
                risk_level = "medium"
                
                for line in lines:
                    if line.startswith("VIOLATES:"):
                        violates = "yes" in line.lower()
                    elif line.startswith("REASON:"):
                        reason = line.replace("REASON:", "").strip()
                    elif line.startswith("RISK_LEVEL:"):
                        risk_level = line.replace("RISK_LEVEL:", "").strip()
                
                if violates:
                    violation = PolicyViolation(
                        violation_id=f"violation_{datetime.now().timestamp()}",
                        policy_id=policy.policy_id,
                        policy_name=policy.name,
                        severity=policy.severity,
                        action=action,
                        context=context,
                        enforcement_action=policy.enforcement_action
                    )
                    return violation
                
                return None
                
            except Exception as e:
                print(f"Error checking policy violation: {e}")
                return None
        
        def enforce_policies(
            self,
            action: str,
            context: Dict[str, Any]
        ) -> Dict[str, Any]:
            """
            Enforce policies on an action.
            
            Returns:
                Dictionary with enforcement result
            """
            is_valid, violations = self.validate_action(action, context)
            
            if is_valid:
                return {
                    "allowed": True,
                    "action": action,
                    "violations": [],
                    "message": "Action complies with all policies"
                }
            
            # Determine enforcement action based on violations
            critical_violations = [
                v for v in violations 
                if v.severity in [PolicySeverity.CRITICAL, PolicySeverity.HIGH]
            ]
            
            if critical_violations:
                # Block critical violations
                return {
                    "allowed": False,
                    "action": None,
                    "violations": violations,
                    "message": f"Action blocked due to {len(critical_violations)} critical policy violations"
                }
            else:
                # Log and warn for lower severity
                return {
                    "allowed": True,
                    "action": action,
                    "violations": violations,
                    "message": f"Action allowed with {len(violations)} policy warnings"
                }
        
        def compose_policies(
            self,
            policy_ids: List[str],
            composition_strategy: str = "all"
        ) -> Policy:
            """
            Compose multiple policies into a single policy.
            
            Args:
                policy_ids: List of policy IDs to compose
                composition_strategy: "all" (AND), "any" (OR)
            """
            policies = [self.policies[pid] for pid in policy_ids if pid in self.policies]
            
            if not policies:
                raise ValueError("No valid policies to compose")
            
            # Create composite policy
            composite = Policy(
                policy_id=f"composite_{datetime.now().timestamp()}",
                name=f"Composite: {', '.join(p.name for p in policies)}",
                description=f"Composite policy combining: {', '.join(p.name for p in policies)}",
                policy_type=PolicyType.COMPLIANCE,
                severity=max(policies, key=lambda p: p.severity.value).severity,
                conditions=[],  # Conditions evaluated separately
                enforcement_action=EnforcementAction.BLOCK,
                priority=max(p.priority for p in policies)
            )
            
            return composite
        
        def get_violations_by_severity(
            self,
            severity: PolicySeverity
        ) -> List[PolicyViolation]:
            """Get violations by severity level."""
            return [v for v in self.violations if v.severity == severity]
        
        def get_policy_summary(self) -> Dict[str, Any]:
            """Get summary of policy system."""
            return {
                "total_policies": len(self.policies),
                "enabled_policies": len([p for p in self.policies.values() if p.enabled]),
                "disabled_policies": len([p for p in self.policies.values() if not p.enabled]),
                "total_violations": len(self.violations),
                "critical_violations": len(self.get_violations_by_severity(PolicySeverity.CRITICAL)),
                "high_violations": len(self.get_violations_by_severity(PolicySeverity.HIGH)),
                "policy_types": {
                    ptype.value: len([p for p in self.policies.values() if p.policy_type == ptype])
                    for ptype in PolicyType
                }
            }
    
    
    def demonstrate_policy_based_control():
        """Demonstrate the policy-based control pattern."""
        print("=" * 80)
        print("Policy-Based Control Pattern Demonstration")
        print("=" * 80)
        
        agent = PolicyBasedControlAgent()
        
        # Demonstration 1: Security Policy
        print("\n" + "=" * 80)
        print("Demonstration 1: Security Policy Enforcement")
        print("=" * 80)
        
        security_policy = Policy(
            policy_id="sec_001",
            name="Data Access Policy",
            description="Restricts access to sensitive data based on user role",
            policy_type=PolicyType.SECURITY,
            severity=PolicySeverity.CRITICAL,
            conditions=[
                PolicyCondition(field="data_type", operator="eq", value="sensitive")
            ],
            enforcement_action=EnforcementAction.BLOCK,
            priority=100
        )
        
        agent.add_policy(security_policy)
        
        # Test action that violates policy
        action = "Access customer payment information"
        context = {
            "data_type": "sensitive",
            "user_role": "analyst",
            "required_role": "admin"
        }
        
        result = agent.enforce_policies(action, context)
        print(f"\nAction: {action}")
        print(f"Allowed: {result['allowed']}")
        print(f"Violations: {len(result['violations'])}")
        print(f"Message: {result['message']}")
        
        # Demonstration 2: Resource Policy
        print("\n" + "=" * 80)
        print("Demonstration 2: Resource Usage Policy")
        print("=" * 80)
        
        resource_policy = Policy(
            policy_id="res_001",
            name="API Rate Limit Policy",
            description="Limits API calls to prevent abuse",
            policy_type=PolicyType.RESOURCE,
            severity=PolicySeverity.HIGH,
            conditions=[
                PolicyCondition(field="api_calls", operator="gt", value=100)
            ],
            enforcement_action=EnforcementAction.BLOCK,
            priority=80
        )
        
        agent.add_policy(resource_policy)
        
        action = "Make API call to external service"
        context = {
            "api_calls": 150,
            "time_window": "1 hour"
        }
        
        result = agent.enforce_policies(action, context)
        print(f"\nAction: {action}")
        print(f"Allowed: {result['allowed']}")
        print(f"Message: {result['message']}")
        
        # Demonstration 3: Content Policy
        print("\n" + "=" * 80)
        print("Demonstration 3: Content Moderation Policy")
        print("=" * 80)
        
        content_policy = Policy(
            policy_id="cont_001",
            name="Content Safety Policy",
            description="Prevents generation of harmful content",
            policy_type=PolicyType.CONTENT,
            severity=PolicySeverity.CRITICAL,
            conditions=[
                PolicyCondition(field="content_category", operator="in", 
                              value=["harmful", "illegal", "offensive"])
            ],
            enforcement_action=EnforcementAction.BLOCK,
            priority=100
        )
        
        agent.add_policy(content_policy)
        
        action = "Generate content about violence"
        context = {
            "content_category": "harmful",
            "user_age": 15
        }
        
        result = agent.enforce_policies(action, context)
        print(f"\nAction: {action}")
        print(f"Allowed: {result['allowed']}")
        print(f"Message: {result['message']}")
        
        # Demonstration 4: Compliance Policy
        print("\n" + "=" * 80)
        print("Demonstration 4: Regulatory Compliance Policy")
        print("=" * 80)
        
        compliance_policy = Policy(
            policy_id="comp_001",
            name="GDPR Compliance Policy",
            description="Ensures GDPR compliance for EU users",
            policy_type=PolicyType.COMPLIANCE,
            severity=PolicySeverity.CRITICAL,
            conditions=[
                PolicyCondition(field="user_location", operator="eq", value="EU"),
                PolicyCondition(field="data_processing", operator="eq", value="personal")
            ],
            enforcement_action=EnforcementAction.BLOCK,
            priority=100
        )
        
        agent.add_policy(compliance_policy)
        
        action = "Process user data for marketing"
        context = {
            "user_location": "EU",
            "data_processing": "personal",
            "consent_given": False
        }
        
        result = agent.enforce_policies(action, context)
        print(f"\nAction: {action}")
        print(f"Allowed: {result['allowed']}")
        print(f"Message: {result['message']}")
        
        # Demonstration 5: Policy Enable/Disable
        print("\n" + "=" * 80)
        print("Demonstration 5: Dynamic Policy Management")
        print("=" * 80)
        
        print("\nDisabling resource policy...")
        agent.disable_policy("res_001")
        
        action = "Make API call to external service"
        context = {
            "api_calls": 150,
            "time_window": "1 hour"
        }
        
        result = agent.enforce_policies(action, context)
        print(f"\nAction: {action}")
        print(f"Allowed: {result['allowed']}")
        print(f"Message: {result['message']}")
        
        print("\nRe-enabling resource policy...")
        agent.enable_policy("res_001")
        
        # Demonstration 6: Multiple Policy Violations
        print("\n" + "=" * 80)
        print("Demonstration 6: Multiple Policy Violations")
        print("=" * 80)
        
        action = "Access and export customer data"
        context = {
            "data_type": "sensitive",
            "user_role": "analyst",
            "user_location": "EU",
            "data_processing": "personal",
            "consent_given": False
        }
        
        is_valid, violations = agent.validate_action(action, context)
        print(f"\nAction: {action}")
        print(f"Valid: {is_valid}")
        print(f"Violations: {len(violations)}")
        for i, violation in enumerate(violations, 1):
            print(f"\n  Violation {i}:")
            print(f"    Policy: {violation.policy_name}")
            print(f"    Severity: {violation.severity.value}")
            print(f"    Action: {violation.enforcement_action.value}")
        
        # Demonstration 7: Policy Priority
        print("\n" + "=" * 80)
        print("Demonstration 7: Policy Priority Handling")
        print("=" * 80)
        
        low_priority_policy = Policy(
            policy_id="low_001",
            name="Low Priority Warning",
            description="Low priority warning policy",
            policy_type=PolicyType.OPERATIONAL,
            severity=PolicySeverity.LOW,
            conditions=[
                PolicyCondition(field="action_type", operator="eq", value="read")
            ],
            enforcement_action=EnforcementAction.LOG,
            priority=10
        )
        
        agent.add_policy(low_priority_policy)
        
        action = "Read configuration file"
        context = {
            "action_type": "read",
            "file_type": "config"
        }
        
        result = agent.enforce_policies(action, context)
        print(f"\nAction: {action}")
        print(f"Allowed: {result['allowed']}")
        print(f"Violations: {len(result['violations'])}")
        print(f"Message: {result['message']}")
        
        # Demonstration 8: Policy Summary
        print("\n" + "=" * 80)
        print("Demonstration 8: Policy System Summary")
        print("=" * 80)
        
        summary = agent.get_policy_summary()
        print("\nPolicy System Summary:")
        print(f"  Total Policies: {summary['total_policies']}")
        print(f"  Enabled: {summary['enabled_policies']}")
        print(f"  Disabled: {summary['disabled_policies']}")
        print(f"  Total Violations: {summary['total_violations']}")
        print(f"  Critical Violations: {summary['critical_violations']}")
        print(f"  High Violations: {summary['high_violations']}")
        print(f"\n  Policies by Type:")
        for ptype, count in summary['policy_types'].items():
            if count > 0:
                print(f"    {ptype}: {count}")
        
        # Summary
        print("\n" + "=" * 80)
        print("Summary: Policy-Based Control Pattern")
        print("=" * 80)
        print("""
    The Policy-Based Control pattern provides comprehensive governance for agent behavior:
    
    Key Features Demonstrated:
    1. Policy Definition - Structured rules with conditions and enforcement actions
    2. Security Policies - Data access control and protection
    3. Resource Policies - API rate limiting and resource governance
    4. Content Policies - Content moderation and safety
    5. Compliance Policies - Regulatory compliance (GDPR, etc.)
    6. Dynamic Management - Enable/disable policies at runtime
    7. Multiple Violations - Handle multiple concurrent policy violations
    8. Priority System - Policy evaluation based on priority
    
    Benefits:
    - Ensures regulatory compliance
    - Enforces organizational policies
    - Provides audit trail
    - Enables fine-grained control
    - Supports policy composition
    - Reduces compliance risk
    
    Best Practices:
    - Design clear, unambiguous policies
    - Use appropriate severity levels
    - Implement efficient policy evaluation
    - Cache policy decisions when possible
    - Log all violations with context
    - Support policy testing
    - Provide policy override mechanisms
    - Monitor policy effectiveness
    - Handle policy conflicts gracefully
    - Document all policies thoroughly
    
    This pattern is essential for production AI systems requiring governance,
    compliance, and controlled agent behavior.
    """)
    
    
    if __name__ == "__main__":
        demonstrate_policy_based_control()
    
        

    Agentic Design Pattern: Policy Based Control

    Pattern 137: Policy Based Control – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Policy Based Control pattern implementation.


    Pattern Description

    Pattern 137: Policy-Based Control

    Description: The Policy-Based Control pattern implements governance mechanisms that enforce organizational policies, regulatory requirements, and operational constraints on agent behavior. This pattern provides a framework for defining, validating, and enforcing policies that control what actions agents can take, what data they can access, and how they should behave in various contexts.

    Policy-based control is essential for production deployments where agents must
    operate within well-defined boundaries. It enables organizations to maintain
    compliance with regulations, enforce security policies, implement business rules,
    and ensure ethical AI behavior. The pattern supports both hard constraints (must
    be followed) and soft constraints (should be followed with exceptions).
    
    This implementation provides a comprehensive policy management system with rule
    definition, policy validation, violation detection, enforcement mechanisms, and
    policy composition. It supports multiple policy types including security policies,
    data policies, behavioral policies, and resource policies, with the ability to
    combine policies and handle conflicts.
    

    Components: – Policy Definition: Structured rules with conditions and actions – Policy Validation: Checks if actions comply with policies – Violation Detection: Identifies policy breaches – Enforcement Mechanisms: Blocks, modifies, or logs violations – Policy Composition: Combines multiple policies – Conflict Resolution: Handles policy conflicts

    Use Cases: – Regulatory compliance (GDPR, HIPAA, SOC2) – Security policy enforcement – Business rule implementation – Ethical AI constraints – Resource usage governance – Data access control – Content moderation – Operational safety

    LangChain Implementation: This implementation uses: – ChatOpenAI for policy validation and interpretation – Custom policy engine for rule enforcement – Structured policy definitions with conditions and actions – LLM-based policy reasoning for complex scenarios – Policy composition and inheritance mechanisms – Violation tracking and audit logging

    Benefits: – Ensures compliance with regulations and standards – Enforces organizational policies consistently – Provides audit trail for policy enforcement – Reduces risk of policy violations – Enables fine-grained control over agent behavior – Supports policy versioning and evolution – Facilitates policy management at scale

    Trade-offs: – May restrict agent flexibility and autonomy – Can increase latency due to policy checks – Requires careful policy design to avoid conflicts – May need ongoing policy maintenance – Can create complexity in policy management – Requires balance between control and capability

    Production Considerations: – Design clear, unambiguous policies – Implement efficient policy evaluation – Cache policy decisions when possible – Log all policy violations with context – Support policy testing and simulation – Implement policy versioning – Provide policy override mechanisms – Monitor policy effectiveness – Support policy composition – Handle policy conflicts gracefully – Implement emergency policy updates – Provide policy documentation


    File Statistics

    • Total Lines: 727
    • Classes: 7
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 137: Policy-Based Control
    
    Description:
        The Policy-Based Control pattern implements governance mechanisms that enforce
        organizational policies, regulatory requirements, and operational constraints on
        agent behavior. This pattern provides a framework for defining, validating, and
        enforcing policies that control what actions agents can take, what data they can
        access, and how they should behave in various contexts.
    
        Policy-based control is essential for production deployments where agents must
        operate within well-defined boundaries. It enables organizations to maintain
        compliance with regulations, enforce security policies, implement business rules,
        and ensure ethical AI behavior. The pattern supports both hard constraints (must
        be followed) and soft constraints (should be followed with exceptions).
    
        This implementation provides a comprehensive policy management system with rule
        definition, policy validation, violation detection, enforcement mechanisms, and
        policy composition. It supports multiple policy types including security policies,
        data policies, behavioral policies, and resource policies, with the ability to
        combine policies and handle conflicts.
    
    Components:
        - Policy Definition: Structured rules with conditions and actions
        - Policy Validation: Checks if actions comply with policies
        - Violation Detection: Identifies policy breaches
        - Enforcement Mechanisms: Blocks, modifies, or logs violations
        - Policy Composition: Combines multiple policies
        - Conflict Resolution: Handles policy conflicts
    
    Use Cases:
        - Regulatory compliance (GDPR, HIPAA, SOC2)
        - Security policy enforcement
        - Business rule implementation
        - Ethical AI constraints
        - Resource usage governance
        - Data access control
        - Content moderation
        - Operational safety
    
    LangChain Implementation:
        This implementation uses:
        - ChatOpenAI for policy validation and interpretation
        - Custom policy engine for rule enforcement
        - Structured policy definitions with conditions and actions
        - LLM-based policy reasoning for complex scenarios
        - Policy composition and inheritance mechanisms
        - Violation tracking and audit logging
    
    Benefits:
        - Ensures compliance with regulations and standards
        - Enforces organizational policies consistently
        - Provides audit trail for policy enforcement
        - Reduces risk of policy violations
        - Enables fine-grained control over agent behavior
        - Supports policy versioning and evolution
        - Facilitates policy management at scale
    
    Trade-offs:
        - May restrict agent flexibility and autonomy
        - Can increase latency due to policy checks
        - Requires careful policy design to avoid conflicts
        - May need ongoing policy maintenance
        - Can create complexity in policy management
        - Requires balance between control and capability
    
    Production Considerations:
        - Design clear, unambiguous policies
        - Implement efficient policy evaluation
        - Cache policy decisions when possible
        - Log all policy violations with context
        - Support policy testing and simulation
        - Implement policy versioning
        - Provide policy override mechanisms
        - Monitor policy effectiveness
        - Support policy composition
        - Handle policy conflicts gracefully
        - Implement emergency policy updates
        - Provide policy documentation
    """
    

    Purpose: This module implements the Policy Based Control pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    import typing.Set
    import typing.Tuple
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Set: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Tuple: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: PolicyType

    Lines 96-105

    Inherits from: Enum

    Purpose:

    Types of policies.
    

    Class: PolicySeverity

    Lines 108-114

    Inherits from: Enum

    Purpose:

    Severity levels for policy violations.
    

    Class: EnforcementAction

    Lines 117-124

    Inherits from: Enum

    Purpose:

    Actions to take when policy is violated.
    

    Class: PolicyCondition

    Lines 128-162

    Purpose:

    Condition for policy rule.
    

    Methods:

    evaluate(self, context)

    Lines 134-162

    Purpose:

    Evaluate condition against context.
    

    Parameters: – context: Context

    Returns: bool


    Class: Policy

    Lines 166-178

    Purpose:

    Policy definition.
    

    Class: PolicyViolation

    Lines 182-192

    Purpose:

    Record of policy violation.
    

    Class: PolicyBasedControlAgent

    Lines 195-446

    Purpose:

    Agent that enforces policy-based control.
    
    This agent manages policies, validates actions against policies,
    detects violations, and enforces policy constraints.
    

    Methods:

    __init__(self, temperature)

    Lines 203-232

    Purpose:

    Initialize the policy control agent.
    

    Parameters: – temperature: Sampling temperature (0-1)

    add_policy(self, policy)

    Lines 234-237

    Purpose:

    Add a policy to the system.
    

    Parameters: – policy: Policy

    Returns: None

    remove_policy(self, policy_id)

    Lines 239-245

    Purpose:

    Remove a policy from the system.
    

    Parameters: – policy_id: Policy id

    Returns: None

    enable_policy(self, policy_id)

    Lines 247-251

    Purpose:

    Enable a policy.
    

    Parameters: – policy_id: Policy id

    Returns: None

    disable_policy(self, policy_id)

    Lines 253-257

    Purpose:

    Disable a policy.
    

    Parameters: – policy_id: Policy id

    Returns: None

    validate_action(self, action, context)

    Lines 259-289

    Purpose:

    Validate an action against all applicable policies.
    
    Returns:
        Tuple of (is_valid, list of violations)
    

    Parameters: – action: Action – context: Context

    Returns: <ast.Subscript object at 0x000001A06D7EFE50>

    _conditions_match(self, conditions, context)

    Lines 291-300

    Purpose:

    Check if all conditions match the context.
    

    Parameters: – conditions: Conditions – context: Context

    Returns: bool

    _check_policy_violation(self, policy, action, context)

    Lines 302-349

    Purpose:

    Check if action violates policy using LLM.
    

    Parameters: – policy: Policy – action: Action – context: Context

    Returns: <ast.Subscript object at 0x000001A06D7BA890>

    enforce_policies(self, action, context)

    Lines 351-393

    Purpose:

    Enforce policies on an action.
    
    Returns:
        Dictionary with enforcement result
    

    Parameters: – action: Action – context: Context

    Returns: <ast.Subscript object at 0x000001A06D63C2D0>

    compose_policies(self, policy_ids, composition_strategy)

    Lines 395-424

    Purpose:

    Compose multiple policies into a single policy.
    
    Args:
        policy_ids: List of policy IDs to compose
        composition_strategy: "all" (AND), "any" (OR)
    

    Parameters: – policy_ids: Policy ids – composition_strategy: Composition strategy

    Returns: Policy

    get_violations_by_severity(self, severity)

    Lines 426-431

    Purpose:

    Get violations by severity level.
    

    Parameters: – severity: Severity

    Returns: <ast.Subscript object at 0x000001A06D7509D0>

    get_policy_summary(self)

    Lines 433-446

    Purpose:

    Get summary of policy system.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D156110>


    Functions

    demonstrate_policy_based_control()

    Lines 449-722

    Purpose:

    Demonstrate the policy-based control pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Policy Based Control pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 136
    • Pattern 138

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Policy Based Control pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 137_policy_based_control.py
    Total Lines: 727
    Pattern Category: AI Agent Design Pattern #137


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Accessibility Focused

    
        """
    Pattern 136: Accessibility-Focused Agent
    
    Description:
        The Accessibility-Focused Agent pattern creates agents designed to be
        inclusive and usable by people with diverse abilities and needs. These
        agents prioritize accessibility features such as clear communication,
        support for assistive technologies, content adaptation, and inclusive
        design principles to ensure everyone can benefit from AI assistance.
        
        Accessibility-focused agents go beyond basic usability to accommodate
        visual, auditory, cognitive, motor, and other impairments. They provide
        alternative formats, clear language, patience with interaction, and
        features that make AI technology available to all users regardless of
        their abilities or circumstances.
        
        This pattern embodies inclusive design principles, ensuring AI agents
        are not just functional but truly accessible to diverse populations
        including people with disabilities, elderly users, non-native speakers,
        and users with temporary limitations.
    
    Key Components:
        1. Clear Communication: Simple, unambiguous language
        2. Alternative Formats: Multiple content representations
        3. Assistive Tech Support: Screen readers, voice control
        4. Flexible Interaction: Multiple input/output methods
        5. Content Adaptation: Adjust to user needs
        6. Error Tolerance: Patient, forgiving interactions
        7. Inclusive Design: Universal accessibility
    
    Accessibility Features:
        1. Visual: Screen reader support, high contrast, text sizing
        2. Auditory: Text alternatives, captions, visual alerts
        3. Cognitive: Clear language, simple structure, consistency
        4. Motor: Keyboard navigation, voice control, large targets
        5. Language: Plain language, translation, glossaries
        6. Context: Help text, examples, clear feedback
        7. Time: No time pressure, save progress, pause
    
    User Accommodations:
        1. Vision impaired: Audio descriptions, clear structure
        2. Hearing impaired: Text alternatives, visual cues
        3. Cognitive differences: Simple language, clear layout
        4. Motor limitations: Alternative inputs, no precision requirements
        5. Language barriers: Clear, simple language, visual aids
        6. Elderly users: Larger text, slower pace, clear instructions
        7. Temporary limitations: Flexible interaction methods
    
    Use Cases:
        - Public service AI assistants
        - Educational platforms
        - Healthcare information systems
        - Government services
        - E-learning applications
        - Banking and finance
        - Emergency services
        - General consumer applications
    
    Advantages:
        - Inclusive user base
        - Legal compliance (ADA, WCAG)
        - Better UX for everyone
        - Broader market reach
        - Social responsibility
        - Reduced support burden
        - Positive brand image
    
    Challenges:
        - Balancing features and complexity
        - Multiple accommodation needs
        - Testing with diverse users
        - Performance overhead
        - Maintaining accessibility
        - Cost of implementation
        - Technical limitations
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Clear, simple language generation
        - Content format adaptation
        - Flexible interaction patterns
        - Accessible error messages
        
    Production Considerations:
        - Follow WCAG guidelines
        - Test with assistive technologies
        - Provide multiple interaction modes
        - Include accessibility settings
        - Document accessibility features
        - Collect user feedback
        - Regular accessibility audits
        - Train on inclusive practices
    """
    
    import os
    from typing import List, Dict, Any, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class AccessibilityNeed(Enum):
        """Types of accessibility needs."""
        VISUAL_IMPAIRMENT = "visual_impairment"
        HEARING_IMPAIRMENT = "hearing_impairment"
        COGNITIVE_DIFFERENCE = "cognitive_difference"
        MOTOR_LIMITATION = "motor_limitation"
        LANGUAGE_BARRIER = "language_barrier"
        ELDERLY = "elderly"
        NONE = "none"
    
    
    class ContentFormat(Enum):
        """Content output formats."""
        TEXT = "text"
        AUDIO_DESCRIPTION = "audio_description"
        SIMPLIFIED_TEXT = "simplified_text"
        STRUCTURED_DATA = "structured_data"
        BULLET_POINTS = "bullet_points"
        STEP_BY_STEP = "step_by_step"
    
    
    class ReadingLevel(Enum):
        """Reading comprehension levels."""
        ELEMENTARY = "elementary"
        MIDDLE_SCHOOL = "middle_school"
        HIGH_SCHOOL = "high_school"
        COLLEGE = "college"
        ADVANCED = "advanced"
    
    
    @dataclass
    class AccessibilityProfile:
        """
        User accessibility profile.
        
        Attributes:
            user_id: User identifier
            accessibility_needs: List of accessibility requirements
            preferred_format: Preferred content format
            reading_level: Reading comprehension level
            font_size: Text size preference (multiplier)
            high_contrast: High contrast mode
            audio_enabled: Audio output enabled
            reduced_motion: Reduce animations
            keyboard_only: Keyboard-only navigation
            screen_reader: Screen reader in use
        """
        user_id: str
        accessibility_needs: List[AccessibilityNeed] = field(default_factory=list)
        preferred_format: ContentFormat = ContentFormat.TEXT
        reading_level: ReadingLevel = ReadingLevel.HIGH_SCHOOL
        font_size: float = 1.0
        high_contrast: bool = False
        audio_enabled: bool = False
        reduced_motion: bool = False
        keyboard_only: bool = False
        screen_reader: bool = False
    
    
    @dataclass
    class AccessibleResponse:
        """
        Accessible response with multiple formats.
        
        Attributes:
            response_id: Unique identifier
            primary_content: Main response
            alternative_formats: Alternative representations
            metadata: Accessibility metadata
            reading_time: Estimated reading time (seconds)
            complexity_score: Content complexity (0-1)
            timestamp: When generated
        """
        response_id: str
        primary_content: str
        alternative_formats: Dict[ContentFormat, str] = field(default_factory=dict)
        metadata: Dict[str, Any] = field(default_factory=dict)
        reading_time: float = 0.0
        complexity_score: float = 0.5
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class AccessibilityAgent:
        """
        Agent focused on accessibility and inclusive design.
        
        This agent adapts content and interaction to accommodate
        diverse user needs and abilities.
        """
        
        def __init__(self, temperature: float = 0.5):
            """
            Initialize accessibility-focused agent.
            
            Args:
                temperature: LLM temperature
            """
            self.llm = ChatOpenAI(temperature=temperature, model="gpt-3.5-turbo")
            self.user_profiles: Dict[str, AccessibilityProfile] = {}
            self.response_history: List[AccessibleResponse] = []
            self.response_counter = 0
        
        def set_user_profile(self, profile: AccessibilityProfile):
            """Set accessibility profile for a user."""
            self.user_profiles[profile.user_id] = profile
        
        def simplify_text(self, text: str, reading_level: ReadingLevel) -> str:
            """
            Simplify text to appropriate reading level.
            
            Args:
                text: Original text
                reading_level: Target reading level
                
            Returns:
                Simplified text
            """
            level_descriptions = {
                ReadingLevel.ELEMENTARY: "a 3rd grader",
                ReadingLevel.MIDDLE_SCHOOL: "a 7th grader",
                ReadingLevel.HIGH_SCHOOL: "a high school student",
                ReadingLevel.COLLEGE: "a college student",
                ReadingLevel.ADVANCED: "an expert"
            }
            
            prompt = ChatPromptTemplate.from_template(
                "Rewrite this text so {target_audience} can understand it easily:\n\n"
                "{text}\n\n"
                "Use:\n"
                "- Simple, common words\n"
                "- Short sentences\n"
                "- Clear structure\n"
                "- Active voice\n"
                "- Concrete examples\n\n"
                "Simplified version:"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            simplified = chain.invoke({
                "text": text,
                "target_audience": level_descriptions[reading_level]
            })
            
            return simplified.strip()
        
        def create_audio_description(self, content: str) -> str:
            """
            Create audio-friendly description.
            
            Args:
                content: Visual content to describe
                
            Returns:
                Audio description
            """
            prompt = ChatPromptTemplate.from_template(
                "Create an audio description for screen readers:\n\n"
                "{content}\n\n"
                "Provide a clear, verbal description that:\n"
                "- Describes visual elements\n"
                "- Explains layout and structure\n"
                "- Indicates interactive elements\n"
                "- Uses clear navigation cues\n\n"
                "Audio description:"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            description = chain.invoke({"content": content})
            return description.strip()
        
        def format_as_steps(self, content: str) -> List[str]:
            """
            Format content as clear steps.
            
            Args:
                content: Content to format
                
            Returns:
                List of steps
            """
            prompt = ChatPromptTemplate.from_template(
                "Break this into clear, numbered steps:\n\n"
                "{content}\n\n"
                "Each step should:\n"
                "- Be one clear action\n"
                "- Use simple language\n"
                "- Start with an action verb\n"
                "- Be easy to follow\n\n"
                "List each step on a new line starting with the number."
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            result = chain.invoke({"content": content})
            
            # Parse steps
            steps = []
            for line in result.strip().split('\n'):
                line = line.strip()
                if line and (line[0].isdigit() or line.startswith('-') or line.startswith('•')):
                    # Remove numbering/bullets
                    step = line.lstrip('0123456789.-• ')
                    if step:
                        steps.append(step)
            
            return steps
        
        def respond(
            self,
            user_input: str,
            user_id: Optional[str] = None
        ) -> AccessibleResponse:
            """
            Generate accessible response.
            
            Args:
                user_input: User's question/request
                user_id: User identifier for profile
                
            Returns:
                Accessible response with multiple formats
            """
            self.response_counter += 1
            response_id = f"resp_{self.response_counter}"
            
            # Get user profile
            profile = self.user_profiles.get(user_id) if user_id else None
            reading_level = profile.reading_level if profile else ReadingLevel.HIGH_SCHOOL
            
            # Generate primary response
            prompt = ChatPromptTemplate.from_template(
                "Provide a clear, helpful response to this question:\n\n"
                "{user_input}\n\n"
                "Use:\n"
                "- Clear, simple language\n"
                "- Short paragraphs\n"
                "- Specific examples\n"
                "- Organized structure\n\n"
                "Response:"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            primary_content = chain.invoke({"user_input": user_input})
            
            # Create alternative formats
            alternative_formats = {}
            
            # Simplified version
            alternative_formats[ContentFormat.SIMPLIFIED_TEXT] = self.simplify_text(
                primary_content,
                ReadingLevel.MIDDLE_SCHOOL
            )
            
            # Step-by-step if applicable
            if any(word in user_input.lower() for word in ['how', 'steps', 'guide', 'do']):
                steps = self.format_as_steps(primary_content)
                alternative_formats[ContentFormat.STEP_BY_STEP] = '\n'.join(
                    f"{i+1}. {step}" for i, step in enumerate(steps)
                )
            
            # Audio description for screen readers
            if profile and profile.screen_reader:
                alternative_formats[ContentFormat.AUDIO_DESCRIPTION] = \
                    self.create_audio_description(primary_content)
            
            # Estimate reading time (average 200 words/min)
            word_count = len(primary_content.split())
            reading_time = (word_count / 200) * 60  # seconds
            
            # Create response
            response = AccessibleResponse(
                response_id=response_id,
                primary_content=primary_content,
                alternative_formats=alternative_formats,
                reading_time=reading_time,
                metadata={
                    "user_id": user_id,
                    "reading_level": reading_level.value if reading_level else None,
                    "word_count": word_count
                }
            )
            
            self.response_history.append(response)
            return response
        
        def provide_help(self, context: str = "general") -> str:
            """
            Provide accessible help information.
            
            Args:
                context: Help context
                
            Returns:
                Help text
            """
            prompt = ChatPromptTemplate.from_template(
                "Provide clear, beginner-friendly help for: {context}\n\n"
                "Include:\n"
                "- What it does (simple explanation)\n"
                "- How to use it (step-by-step)\n"
                "- Common issues and solutions\n"
                "- Where to get more help\n\n"
                "Use very simple language. Be encouraging and supportive."
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            help_text = chain.invoke({"context": context})
            return help_text
        
        def check_accessibility(self, content: str) -> Dict[str, Any]:
            """
            Check content for accessibility issues.
            
            Args:
                content: Content to check
                
            Returns:
                Accessibility assessment
            """
            prompt = ChatPromptTemplate.from_template(
                "Review this content for accessibility:\n\n"
                "{content}\n\n"
                "Check for:\n"
                "1. Reading level (is it clear and simple?)\n"
                "2. Structure (is it well organized?)\n"
                "3. Language (avoids jargon and complex terms?)\n"
                "4. Length (appropriate, not overwhelming?)\n"
                "5. Clarity (easy to understand?)\n\n"
                "Provide:\n"
                "SCORE: 0-10\n"
                "ISSUES: [list any problems]\n"
                "SUGGESTIONS: [how to improve]"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            assessment = chain.invoke({"content": content})
            
            # Parse assessment
            score = 7.0  # default
            lines = assessment.split('\n')
            for line in lines:
                if line.startswith("SCORE:"):
                    try:
                        score = float(line.split(":")[1].strip().split()[0])
                    except:
                        pass
            
            return {
                "score": score,
                "assessment": assessment,
                "accessible": score >= 7.0
            }
        
        def get_accessibility_report(self) -> Dict[str, Any]:
            """Get accessibility usage report."""
            if not self.response_history:
                return {
                    "total_responses": 0,
                    "avg_reading_time": 0.0,
                    "formats_provided": []
                }
            
            total_reading_time = sum(r.reading_time for r in self.response_history)
            avg_reading_time = total_reading_time / len(self.response_history)
            
            # Count formats
            format_counts = {}
            for response in self.response_history:
                for format_type in response.alternative_formats.keys():
                    format_counts[format_type] = format_counts.get(format_type, 0) + 1
            
            return {
                "total_responses": len(self.response_history),
                "avg_reading_time": avg_reading_time,
                "formats_provided": list(format_counts.keys()),
                "format_usage": {fmt.value: count for fmt, count in format_counts.items()},
                "users_served": len(self.user_profiles)
            }
    
    
    def demonstrate_accessibility():
        """Demonstrate accessibility-focused agent pattern."""
        
        print("=" * 80)
        print("ACCESSIBILITY-FOCUSED AGENT PATTERN DEMONSTRATION")
        print("=" * 80)
        
        agent = AccessibilityAgent()
        
        # Example 1: User profiles
        print("\n" + "=" * 80)
        print("Example 1: Accessibility Profiles")
        print("=" * 80)
        
        profiles = [
            AccessibilityProfile(
                user_id="user1",
                accessibility_needs=[AccessibilityNeed.VISUAL_IMPAIRMENT],
                screen_reader=True,
                audio_enabled=True,
                reading_level=ReadingLevel.MIDDLE_SCHOOL
            ),
            AccessibilityProfile(
                user_id="user2",
                accessibility_needs=[AccessibilityNeed.COGNITIVE_DIFFERENCE],
                preferred_format=ContentFormat.STEP_BY_STEP,
                reading_level=ReadingLevel.ELEMENTARY,
                reduced_motion=True
            ),
            AccessibilityProfile(
                user_id="user3",
                accessibility_needs=[AccessibilityNeed.ELDERLY],
                font_size=1.5,
                high_contrast=True,
                reading_level=ReadingLevel.HIGH_SCHOOL
            )
        ]
        
        for profile in profiles:
            agent.set_user_profile(profile)
            print(f"\nProfile: {profile.user_id}")
            print(f"  Needs: {[need.value for need in profile.accessibility_needs]}")
            print(f"  Reading Level: {profile.reading_level.value}")
            print(f"  Screen Reader: {profile.screen_reader}")
        
        # Example 2: Simplified text
        print("\n" + "=" * 80)
        print("Example 2: Text Simplification")
        print("=" * 80)
        
        complex_text = """
        The implementation leverages sophisticated algorithms to optimize 
        performance characteristics through parallelization and caching mechanisms,
        thereby enhancing computational efficiency and reducing latency.
        """
        
        print("\nOriginal (Complex):")
        print(complex_text)
        
        simplified = agent.simplify_text(complex_text, ReadingLevel.MIDDLE_SCHOOL)
        print("\nSimplified (Middle School Level):")
        print(simplified)
        
        # Example 3: Step-by-step format
        print("\n" + "=" * 80)
        print("Example 3: Step-by-Step Instructions")
        print("=" * 80)
        
        content = "To reset your password, access the settings, find security options, and select password reset."
        
        print("\nOriginal:")
        print(content)
        
        steps = agent.format_as_steps(content)
        print("\nAs Steps:")
        for i, step in enumerate(steps, 1):
            print(f"{i}. {step}")
        
        # Example 4: Accessible responses
        print("\n" + "=" * 80)
        print("Example 4: Accessible Responses with Multiple Formats")
        print("=" * 80)
        
        question = "How do I change my account settings?"
        
        print(f"\nQuestion: {question}")
        print(f"User: user2 (needs: cognitive support, step-by-step)")
        
        response = agent.respond(question, user_id="user2")
        
        print(f"\nPrimary Response:")
        print(response.primary_content[:200] + "...")
        
        print(f"\nAlternative Formats Available:")
        for format_type in response.alternative_formats.keys():
            print(f"  - {format_type.value}")
        
        if ContentFormat.STEP_BY_STEP in response.alternative_formats:
            print(f"\nStep-by-Step Version:")
            print(response.alternative_formats[ContentFormat.STEP_BY_STEP])
        
        print(f"\nReading Time: {response.reading_time:.0f} seconds")
        
        # Example 5: Screen reader support
        print("\n" + "=" * 80)
        print("Example 5: Screen Reader Audio Descriptions")
        print("=" * 80)
        
        visual_content = "A login form with email field, password field, and login button"
        
        print(f"\nVisual Content: {visual_content}")
        
        audio_desc = agent.create_audio_description(visual_content)
        print(f"\nAudio Description for Screen Readers:")
        print(audio_desc)
        
        # Example 6: Help system
        print("\n" + "=" * 80)
        print("Example 6: Accessible Help System")
        print("=" * 80)
        
        print("\nRequesting help for: 'uploading files'")
        
        help_text = agent.provide_help("uploading files")
        print(f"\nHelp Content:")
        print(help_text[:400] + "...")
        
        # Example 7: Accessibility checking
        print("\n" + "=" * 80)
        print("Example 7: Content Accessibility Assessment")
        print("=" * 80)
        
        test_content = "This is a simple, clear explanation that anyone can understand."
        
        print(f"\nChecking content: \"{test_content}\"")
        
        assessment = agent.check_accessibility(test_content)
        print(f"\nAccessibility Score: {assessment['score']}/10")
        print(f"Accessible: {assessment['accessible']}")
        
        # Example 8: Usage report
        print("\n" + "=" * 80)
        print("Example 8: Accessibility Usage Report")
        print("=" * 80)
        
        # Generate some responses
        test_questions = [
            "What is AI?",
            "How do I sign up?",
            "Explain machine learning"
        ]
        
        for q in test_questions:
            agent.respond(q, user_id="user1")
        
        report = agent.get_accessibility_report()
        
        print("\nACCESSIBILITY REPORT:")
        print("=" * 60)
        print(f"Total Responses: {report['total_responses']}")
        print(f"Average Reading Time: {report['avg_reading_time']:.0f} seconds")
        print(f"Users Served: {report['users_served']}")
        print(f"\nFormats Provided:")
        for format_name, count in report.get('format_usage', {}).items():
            print(f"  {format_name}: {count}")
        
        # Summary
        print("\n" + "=" * 80)
        print("SUMMARY: Accessibility-Focused Agent Pattern")
        print("=" * 80)
        
        summary = """
        The Accessibility-Focused Agent pattern demonstrated:
        
        1. USER PROFILES (Example 1):
           - Accessibility needs tracking
           - Individual preferences
           - Assistive technology support
           - Reading level customization
           - Visual preferences
        
        2. TEXT SIMPLIFICATION (Example 2):
           - Reading level adaptation
           - Complex to simple conversion
           - Clear language
           - Appropriate vocabulary
           - Comprehension support
        
        3. STRUCTURED FORMATS (Example 3):
           - Step-by-step instructions
           - Clear organization
           - Easy-to-follow format
           - Actionable guidance
           - Sequential clarity
        
        4. MULTIPLE FORMATS (Example 4):
           - Primary content
           - Alternative representations
           - Format flexibility
           - User choice
           - Comprehensive options
        
        5. SCREEN READER SUPPORT (Example 5):
           - Audio descriptions
           - Verbal navigation
           - Structure explanation
           - Accessible interaction
           - Non-visual access
        
        6. HELP SYSTEM (Example 6):
           - Clear, simple help
           - Beginner-friendly
           - Encouraging tone
           - Practical guidance
           - Support resources
        
        7. QUALITY ASSURANCE (Example 7):
           - Accessibility scoring
           - Content assessment
           - Issue identification
           - Improvement suggestions
           - Standards compliance
        
        8. MONITORING (Example 8):
           - Usage tracking
           - Format analytics
           - Performance metrics
           - User statistics
           - Continuous improvement
        
        KEY BENEFITS:
        ✓ Inclusive user base
        ✓ Legal compliance (ADA, WCAG)
        ✓ Better UX for everyone
        ✓ Broader market reach
        ✓ Social responsibility
        ✓ Reduced support burden
        ✓ Positive brand image
        ✓ Universal usability
        
        USE CASES:
        • Public service AI assistants
        • Educational platforms
        • Healthcare information
        • Government services
        • E-learning applications
        • Banking and finance
        • Emergency services
        • Consumer applications
        
        ACCESSIBILITY FEATURES:
        → Visual: Screen readers, high contrast, text sizing
        → Auditory: Text alternatives, captions, visual alerts
        → Cognitive: Clear language, simple structure
        → Motor: Keyboard navigation, voice control
        → Language: Plain language, translation
        → Context: Help text, examples, clear feedback
        → Time: No pressure, save progress, pause
        
        USER ACCOMMODATIONS:
        • Vision impaired: Audio descriptions
        • Hearing impaired: Text alternatives
        • Cognitive differences: Simple language
        • Motor limitations: Alternative inputs
        • Language barriers: Clear communication
        • Elderly users: Larger text, slower pace
        • Temporary limitations: Flexible methods
        
        BEST PRACTICES:
        1. Follow WCAG guidelines
        2. Test with assistive technologies
        3. Provide multiple interaction modes
        4. Include accessibility settings
        5. Document accessibility features
        6. Collect user feedback
        7. Regular accessibility audits
        8. Train on inclusive practices
        
        TRADE-OFFS:
        • Features vs. simplicity
        • Customization vs. consistency
        • Performance vs. alternatives
        • Automation vs. user control
        
        PRODUCTION CONSIDERATIONS:
        → Comply with ADA and WCAG standards
        → Test with real assistive technologies
        → Provide clear documentation
        → Support keyboard-only navigation
        → Ensure color contrast ratios
        → Include skip navigation links
        → Provide text alternatives
        → Enable font size adjustment
        → Support screen magnification
        → Test with diverse users
        
        This pattern ensures AI agents are truly inclusive, making technology
        accessible to all users regardless of their abilities, creating a more
        equitable and usable experience for everyone.
        """
        
        print(summary)
    
    
    if __name__ == "__main__":
        demonstrate_accessibility()
    
        

    Agentic Design Pattern: Accessibility Focused

    Pattern 136: Accessibility Focused – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Accessibility Focused pattern implementation.


    Pattern Description

    Pattern 136: Accessibility-Focused Agent

    Description: The Accessibility-Focused Agent pattern creates agents designed to be inclusive and usable by people with diverse abilities and needs. These agents prioritize accessibility features such as clear communication, support for assistive technologies, content adaptation, and inclusive design principles to ensure everyone can benefit from AI assistance.

    Accessibility-focused agents go beyond basic usability to accommodate
    visual, auditory, cognitive, motor, and other impairments. They provide
    alternative formats, clear language, patience with interaction, and
    features that make AI technology available to all users regardless of
    their abilities or circumstances.
    
    This pattern embodies inclusive design principles, ensuring AI agents
    are not just functional but truly accessible to diverse populations
    including people with disabilities, elderly users, non-native speakers,
    and users with temporary limitations.
    

    Key Components: 1. Clear Communication: Simple, unambiguous language 2. Alternative Formats: Multiple content representations 3. Assistive Tech Support: Screen readers, voice control 4. Flexible Interaction: Multiple input/output methods 5. Content Adaptation: Adjust to user needs 6. Error Tolerance: Patient, forgiving interactions 7. Inclusive Design: Universal accessibility

    Accessibility Features: 1. Visual: Screen reader support, high contrast, text sizing 2. Auditory: Text alternatives, captions, visual alerts 3. Cognitive: Clear language, simple structure, consistency 4. Motor: Keyboard navigation, voice control, large targets 5. Language: Plain language, translation, glossaries 6. Context: Help text, examples, clear feedback 7. Time: No time pressure, save progress, pause

    User Accommodations: 1. Vision impaired: Audio descriptions, clear structure 2. Hearing impaired: Text alternatives, visual cues 3. Cognitive differences: Simple language, clear layout 4. Motor limitations: Alternative inputs, no precision requirements 5. Language barriers: Clear, simple language, visual aids 6. Elderly users: Larger text, slower pace, clear instructions 7. Temporary limitations: Flexible interaction methods

    Use Cases: – Public service AI assistants – Educational platforms – Healthcare information systems – Government services – E-learning applications – Banking and finance – Emergency services – General consumer applications

    Advantages: – Inclusive user base – Legal compliance (ADA, WCAG) – Better UX for everyone – Broader market reach – Social responsibility – Reduced support burden – Positive brand image

    Challenges: – Balancing features and complexity – Multiple accommodation needs – Testing with diverse users – Performance overhead – Maintaining accessibility – Cost of implementation – Technical limitations

    LangChain Implementation: This implementation uses LangChain for: – Clear, simple language generation – Content format adaptation – Flexible interaction patterns – Accessible error messages

    Production Considerations: – Follow WCAG guidelines – Test with assistive technologies – Provide multiple interaction modes – Include accessibility settings – Document accessibility features – Collect user feedback – Regular accessibility audits – Train on inclusive practices


    File Statistics

    • Total Lines: 799
    • Classes: 6
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 136: Accessibility-Focused Agent
    
    Description:
        The Accessibility-Focused Agent pattern creates agents designed to be
        inclusive and usable by people with diverse abilities and needs. These
        agents prioritize accessibility features such as clear communication,
        support for assistive technologies, content adaptation, and inclusive
        design principles to ensure everyone can benefit from AI assistance.
    
        Accessibility-focused agents go beyond basic usability to accommodate
        visual, auditory, cognitive, motor, and other impairments. They provide
        alternative formats, clear language, patience with interaction, and
        features that make AI technology available to all users regardless of
        their abilities or circumstances.
    
        This pattern embodies inclusive design principles, ensuring AI agents
        are not just functional but truly accessible to diverse populations
        including people with disabilities, elderly users, non-native speakers,
        and users with temporary limitations.
    
    Key Components:
        1. Clear Communication: Simple, unambiguous language
        2. Alternative Formats: Multiple content representations
        3. Assistive Tech Support: Screen readers, voice control
        4. Flexible Interaction: Multiple input/output methods
        5. Content Adaptation: Adjust to user needs
        6. Error Tolerance: Patient, forgiving interactions
        7. Inclusive Design: Universal accessibility
    
    Accessibility Features:
        1. Visual: Screen reader support, high contrast, text sizing
        2. Auditory: Text alternatives, captions, visual alerts
        3. Cognitive: Clear language, simple structure, consistency
        4. Motor: Keyboard navigation, voice control, large targets
        5. Language: Plain language, translation, glossaries
        6. Context: Help text, examples, clear feedback
        7. Time: No time pressure, save progress, pause
    
    User Accommodations:
        1. Vision impaired: Audio descriptions, clear structure
        2. Hearing impaired: Text alternatives, visual cues
        3. Cognitive differences: Simple language, clear layout
        4. Motor limitations: Alternative inputs, no precision requirements
        5. Language barriers: Clear, simple language, visual aids
        6. Elderly users: Larger text, slower pace, clear instructions
        7. Temporary limitations: Flexible interaction methods
    
    Use Cases:
        - Public service AI assistants
        - Educational platforms
        - Healthcare information systems
        - Government services
        - E-learning applications
        - Banking and finance
        - Emergency services
        - General consumer applications
    
    Advantages:
        - Inclusive user base
        - Legal compliance (ADA, WCAG)
        - Better UX for everyone
        - Broader market reach
        - Social responsibility
        - Reduced support burden
        - Positive brand image
    
    Challenges:
        - Balancing features and complexity
        - Multiple accommodation needs
        - Testing with diverse users
        - Performance overhead
        - Maintaining accessibility
        - Cost of implementation
        - Technical limitations
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Clear, simple language generation
        - Content format adaptation
        - Flexible interaction patterns
        - Accessible error messages
    
    Production Considerations:
        - Follow WCAG guidelines
        - Test with assistive technologies
        - Provide multiple interaction modes
        - Include accessibility settings
        - Document accessibility features
        - Collect user feedback
        - Regular accessibility audits
        - Train on inclusive practices
    """
    

    Purpose: This module implements the Accessibility Focused pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: AccessibilityNeed

    Lines 109-117

    Inherits from: Enum

    Purpose:

    Types of accessibility needs.
    

    Class: ContentFormat

    Lines 120-127

    Inherits from: Enum

    Purpose:

    Content output formats.
    

    Class: ReadingLevel

    Lines 130-136

    Inherits from: Enum

    Purpose:

    Reading comprehension levels.
    

    Class: AccessibilityProfile

    Lines 140-165

    Purpose:

    User accessibility profile.
    
    Attributes:
        user_id: User identifier
        accessibility_needs: List of accessibility requirements
        preferred_format: Preferred content format
        reading_level: Reading comprehension level
        font_size: Text size preference (multiplier)
        high_contrast: High contrast mode
        audio_enabled: Audio output enabled
        reduced_motion: Reduce animations
        keyboard_only: Keyboard-only navigation
        screen_reader: Screen reader in use
    

    Class: AccessibleResponse

    Lines 169-188

    Purpose:

    Accessible response with multiple formats.
    
    Attributes:
        response_id: Unique identifier
        primary_content: Main response
        alternative_formats: Alternative representations
        metadata: Accessibility metadata
        reading_time: Estimated reading time (seconds)
        complexity_score: Content complexity (0-1)
        timestamp: When generated
    

    Class: AccessibilityAgent

    Lines 191-490

    Purpose:

    Agent focused on accessibility and inclusive design.
    
    This agent adapts content and interaction to accommodate
    diverse user needs and abilities.
    

    Methods:

    __init__(self, temperature)

    Lines 199-209

    Purpose:

    Initialize accessibility-focused agent.
    
    Args:
        temperature: LLM temperature
    

    Parameters: – temperature: Sampling temperature (0-1)

    set_user_profile(self, profile)

    Lines 211-213

    Purpose:

    Set accessibility profile for a user.
    

    Parameters: – profile: Profile

    simplify_text(self, text, reading_level)

    Lines 215-253

    Purpose:

    Simplify text to appropriate reading level.
    
    Args:
        text: Original text
        reading_level: Target reading level
    
    Returns:
        Simplified text
    

    Parameters: – text: Text – reading_level: Reading level

    Returns: str

    create_audio_description(self, content)

    Lines 255-279

    Purpose:

    Create audio-friendly description.
    
    Args:
        content: Visual content to describe
    
    Returns:
        Audio description
    

    Parameters: – content: Content

    Returns: str

    format_as_steps(self, content)

    Lines 281-316

    Purpose:

    Format content as clear steps.
    
    Args:
        content: Content to format
    
    Returns:
        List of steps
    

    Parameters: – content: Content

    Returns: <ast.Subscript object at 0x000001A06D74B450>

    respond(self, user_input, user_id)

    Lines 318-394

    Purpose:

    Generate accessible response.
    
    Args:
        user_input: User's question/request
        user_id: User identifier for profile
    
    Returns:
        Accessible response with multiple formats
    

    Parameters: – user_input: Input data – user_id: User id

    Returns: AccessibleResponse

    provide_help(self, context)

    Lines 396-419

    Purpose:

    Provide accessible help information.
    
    Args:
        context: Help context
    
    Returns:
        Help text
    

    Parameters: – context: Context

    Returns: str

    check_accessibility(self, content)

    Lines 421-464

    Purpose:

    Check content for accessibility issues.
    
    Args:
        content: Content to check
    
    Returns:
        Accessibility assessment
    

    Parameters: – content: Content

    Returns: <ast.Subscript object at 0x000001A06D825FD0>

    get_accessibility_report(self)

    Lines 466-490

    Purpose:

    Get accessibility usage report.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D60E9D0>


    Functions

    demonstrate_accessibility()

    Lines 493-794

    Purpose:

    Demonstrate accessibility-focused agent pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Accessibility Focused pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 135
    • Pattern 137

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Accessibility Focused pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 136_accessibility_focused.py
    Total Lines: 799
    Pattern Category: AI Agent Design Pattern #136


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Polyglot Agent

    
        """
    Pattern 135: Polyglot Agent
    
    Description:
        The Polyglot Agent pattern creates agents capable of understanding and
        generating content in multiple languages. Unlike single-language agents,
        polyglot agents can seamlessly switch between languages, translate content,
        detect language automatically, and maintain context across language boundaries.
        They understand cultural nuances, idioms, and context-specific language usage.
        
        Polyglot agents are essential for global applications where users speak different
        languages, content needs translation, or multilingual support is required. They
        go beyond simple translation to understand context, maintain consistency across
        languages, and adapt tone appropriately for different cultures.
        
        This pattern enables truly global AI applications that can serve users in their
        native languages while maintaining quality and coherence across all interactions.
    
    Key Components:
        1. Language Detection: Automatic language identification
        2. Translation Engine: High-quality translation
        3. Context Preservation: Maintain meaning across languages
        4. Cultural Adaptation: Culturally appropriate responses
        5. Language Memory: Track language preferences
        6. Multilingual Knowledge: Language-specific information
        7. Quality Validation: Translation accuracy checks
    
    Language Capabilities:
        1. Detection: Identify input language
        2. Translation: Convert between languages
        3. Generation: Create content in any language
        4. Code-Switching: Handle mixed-language input
        5. Localization: Adapt to regional variants
        6. Transcreation: Culturally adapt content
        7. Validation: Check translation quality
    
    Supported Features:
        1. Multiple Languages: Support for many languages
        2. Automatic Detection: Identify language without prompting
        3. Context Awareness: Understand conversation flow
        4. Cultural Sensitivity: Respect cultural differences
        5. Consistent Terminology: Maintain vocabulary across languages
        6. Bidirectional: Handle any language pair
        7. Real-time: Fast language processing
    
    Use Cases:
        - Global customer support
        - Multilingual content generation
        - International e-commerce
        - Language learning applications
        - Global documentation
        - Multilingual chatbots
        - International business communication
        - Content localization
    
    Advantages:
        - Global reach
        - Better user experience
        - Market expansion
        - Cultural inclusivity
        - Reduced translation costs
        - Real-time multilingual support
        - Consistent brand voice
    
    Challenges:
        - Translation accuracy
        - Cultural nuances
        - Idiom handling
        - Context preservation
        - Language model quality
        - Regional variations
        - Technical terminology
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Language detection
        - Translation chains
        - Multilingual generation
        - Context tracking
        
    Production Considerations:
        - Support major languages first
        - Provide human translation fallback
        - Track translation quality
        - Handle rare languages gracefully
        - Cache common translations
        - Monitor language coverage
        - Respect regional preferences
        - Enable language selection override
    """
    
    import os
    from typing import List, Dict, Any, Optional, Tuple
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class Language(Enum):
        """Supported languages."""
        ENGLISH = "en"
        SPANISH = "es"
        FRENCH = "fr"
        GERMAN = "de"
        ITALIAN = "it"
        PORTUGUESE = "pt"
        RUSSIAN = "ru"
        JAPANESE = "ja"
        KOREAN = "ko"
        CHINESE = "zh"
        ARABIC = "ar"
        HINDI = "hi"
        UNKNOWN = "unknown"
    
    
    @dataclass
    class LanguagePreference:
        """
        User language preferences.
        
        Attributes:
            primary_language: Main language
            secondary_languages: Alternative languages
            regional_variant: Regional dialect (e.g., en-US, en-GB)
            formality_level: Formal or informal
        """
        primary_language: Language
        secondary_languages: List[Language] = field(default_factory=list)
        regional_variant: Optional[str] = None
        formality_level: str = "neutral"
    
    
    @dataclass
    class MultilingualMessage:
        """
        Message with language information.
        
        Attributes:
            message_id: Unique identifier
            content: Message content
            detected_language: Detected language
            target_language: Desired output language
            translation: Translated content if applicable
            confidence: Language detection confidence
            timestamp: When created
        """
        message_id: str
        content: str
        detected_language: Language
        target_language: Optional[Language] = None
        translation: Optional[str] = None
        confidence: float = 0.0
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class PolyglotAgent:
        """
        Agent with multilingual capabilities.
        
        This agent can understand and generate content in multiple
        languages with context preservation and cultural awareness.
        """
        
        def __init__(self, temperature: float = 0.5):
            """
            Initialize polyglot agent.
            
            Args:
                temperature: LLM temperature
            """
            self.llm = ChatOpenAI(temperature=temperature, model="gpt-3.5-turbo")
            self.conversation_history: List[MultilingualMessage] = []
            self.message_counter = 0
            self.user_preferences: Dict[str, LanguagePreference] = {}
            
            # Common phrases in different languages for detection
            self.language_patterns = {
                Language.ENGLISH: ["hello", "thank you", "please", "the", "is", "are"],
                Language.SPANISH: ["hola", "gracias", "por favor", "el", "la", "es"],
                Language.FRENCH: ["bonjour", "merci", "s'il vous plaît", "le", "la", "est"],
                Language.GERMAN: ["hallo", "danke", "bitte", "der", "die", "ist"],
                Language.ITALIAN: ["ciao", "grazie", "per favore", "il", "la", "è"],
                Language.PORTUGUESE: ["olá", "obrigado", "por favor", "o", "a", "é"],
            }
        
        def detect_language(self, text: str) -> Tuple[Language, float]:
            """
            Detect language of text.
            
            Args:
                text: Input text
                
            Returns:
                Detected language and confidence
            """
            text_lower = text.lower()
            
            # Simple pattern matching for demo
            language_scores = {}
            for language, patterns in self.language_patterns.items():
                score = sum(1 for pattern in patterns if pattern in text_lower)
                if score > 0:
                    language_scores[language] = score
            
            if language_scores:
                detected = max(language_scores, key=language_scores.get)
                max_score = language_scores[detected]
                confidence = min(0.9, max_score / len(self.language_patterns[detected]))
                return detected, confidence
            
            # Fallback to LLM detection
            prompt = ChatPromptTemplate.from_template(
                "Detect the language of this text: \"{text}\"\n\n"
                "Respond with just the language code (en, es, fr, de, it, pt, ru, ja, ko, zh, ar, hi)"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            result = chain.invoke({"text": text})
            
            # Map result to Language enum
            code = result.strip().lower()[:2]
            for lang in Language:
                if lang.value == code:
                    return lang, 0.7
            
            return Language.UNKNOWN, 0.3
        
        def translate(
            self,
            text: str,
            source_language: Language,
            target_language: Language,
            context: Optional[str] = None
        ) -> str:
            """
            Translate text between languages.
            
            Args:
                text: Text to translate
                source_language: Source language
                target_language: Target language
                context: Optional context
                
            Returns:
                Translated text
            """
            if source_language == target_language:
                return text
            
            prompt_template = (
                "Translate the following text from {source} to {target}.\n"
            )
            
            if context:
                prompt_template += "Context: {context}\n"
            
            prompt_template += (
                "Maintain the tone, meaning, and cultural appropriateness.\n\n"
                "Text: {text}\n\n"
                "Translation:"
            )
            
            prompt = ChatPromptTemplate.from_template(prompt_template)
            chain = prompt | self.llm | StrOutputParser()
            
            input_data = {
                "text": text,
                "source": source_language.name,
                "target": target_language.name
            }
            
            if context:
                input_data["context"] = context
            
            translation = chain.invoke(input_data)
            return translation.strip()
        
        def respond(
            self,
            user_input: str,
            target_language: Optional[Language] = None,
            user_id: Optional[str] = None
        ) -> str:
            """
            Respond to user in appropriate language.
            
            Args:
                user_input: User's message
                target_language: Desired response language (auto-detect if None)
                user_id: User identifier for preferences
                
            Returns:
                Response in target language
            """
            # Detect input language
            detected_lang, confidence = self.detect_language(user_input)
            
            # Determine target language
            if target_language is None:
                # Check user preferences
                if user_id and user_id in self.user_preferences:
                    target_language = self.user_preferences[user_id].primary_language
                else:
                    # Default to input language
                    target_language = detected_lang
            
            # Store message
            self.message_counter += 1
            message = MultilingualMessage(
                message_id=f"msg_{self.message_counter}",
                content=user_input,
                detected_language=detected_lang,
                target_language=target_language,
                confidence=confidence
            )
            self.conversation_history.append(message)
            
            # Generate response
            prompt = ChatPromptTemplate.from_template(
                "Respond to this message in {target_language}:\n\n"
                "User message: {user_input}\n"
                "(Detected language: {detected_language})\n\n"
                "Provide a helpful response in {target_language}, maintaining "
                "appropriate cultural context and tone."
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            response = chain.invoke({
                "user_input": user_input,
                "target_language": target_language.name,
                "detected_language": detected_lang.name
            })
            
            return response
        
        def set_user_preference(self, user_id: str, preference: LanguagePreference):
            """Set language preferences for a user."""
            self.user_preferences[user_id] = preference
        
        def handle_mixed_language(self, text: str) -> Dict[str, Any]:
            """
            Handle text with multiple languages (code-switching).
            
            Args:
                text: Mixed-language text
                
            Returns:
                Analysis of language segments
            """
            prompt = ChatPromptTemplate.from_template(
                "This text contains multiple languages:\n\n"
                "\"{text}\"\n\n"
                "Identify the languages used and provide:\n"
                "1. List of languages detected\n"
                "2. Dominant language\n"
                "3. Translation to English if needed"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            analysis = chain.invoke({"text": text})
            
            return {
                "original_text": text,
                "analysis": analysis
            }
        
        def localize_content(
            self,
            content: str,
            target_language: Language,
            region: Optional[str] = None
        ) -> str:
            """
            Localize content for specific language and region.
            
            Args:
                content: Content to localize
                target_language: Target language
                region: Regional variant (e.g., US, UK, BR)
                
            Returns:
                Localized content
            """
            prompt_template = (
                "Localize this content for {target_language}"
            )
            
            if region:
                prompt_template += " ({region} region)"
            
            prompt_template += (
                ".\n\n"
                "Original content:\n"
                "{content}\n\n"
                "Adapt idioms, cultural references, units, dates, and formats "
                "to be appropriate for the target audience.\n\n"
                "Localized content:"
            )
            
            prompt = ChatPromptTemplate.from_template(prompt_template)
            chain = prompt | self.llm | StrOutputParser()
            
            input_data = {
                "content": content,
                "target_language": target_language.name
            }
            
            if region:
                input_data["region"] = region
            
            localized = chain.invoke(input_data)
            return localized.strip()
        
        def get_language_statistics(self) -> Dict[str, Any]:
            """Get statistics about language usage."""
            if not self.conversation_history:
                return {
                    "total_messages": 0,
                    "languages_detected": [],
                    "most_common": None
                }
            
            language_counts = {}
            for msg in self.conversation_history:
                lang = msg.detected_language
                language_counts[lang] = language_counts.get(lang, 0) + 1
            
            most_common = max(language_counts, key=language_counts.get) if language_counts else None
            
            return {
                "total_messages": len(self.conversation_history),
                "languages_detected": list(language_counts.keys()),
                "language_distribution": {lang.name: count for lang, count in language_counts.items()},
                "most_common": most_common.name if most_common else None
            }
    
    
    def demonstrate_polyglot():
        """Demonstrate polyglot agent pattern."""
        
        print("=" * 80)
        print("POLYGLOT AGENT PATTERN DEMONSTRATION")
        print("=" * 80)
        
        agent = PolyglotAgent()
        
        # Example 1: Language detection
        print("\n" + "=" * 80)
        print("Example 1: Automatic Language Detection")
        print("=" * 80)
        
        test_phrases = [
            "Hello, how are you?",
            "Hola, ¿cómo estás?",
            "Bonjour, comment allez-vous?",
            "Hallo, wie geht es dir?",
            "Ciao, come stai?"
        ]
        
        print("\nDetecting languages:")
        for phrase in test_phrases:
            detected, confidence = agent.detect_language(phrase)
            print(f'\n"{phrase}"')
            print(f"  → Language: {detected.name} (confidence: {confidence:.2f})")
        
        # Example 2: Translation
        print("\n" + "=" * 80)
        print("Example 2: Translation Between Languages")
        print("=" * 80)
        
        original = "I love learning new languages!"
        source = Language.ENGLISH
        targets = [Language.SPANISH, Language.FRENCH, Language.GERMAN]
        
        print(f"\nOriginal ({source.name}): {original}")
        print("\nTranslations:")
        
        for target in targets:
            translation = agent.translate(original, source, target)
            print(f"  {target.name}: {translation}")
        
        # Example 3: Multilingual conversation
        print("\n" + "=" * 80)
        print("Example 3: Multilingual Conversation")
        print("=" * 80)
        
        print("\nConversation with automatic language switching:")
        
        messages = [
            ("Hello! Can you help me?", None),
            ("Sí, ¿en qué puedo ayudarte?", Language.SPANISH),
            ("Thanks! Do you speak French too?", Language.ENGLISH)
        ]
        
        for msg, target_lang in messages:
            detected, conf = agent.detect_language(msg)
            print(f'\nUser ({detected.name}): {msg}')
            response = agent.respond(msg, target_language=target_lang)
            print(f'Agent: {response}')
        
        # Example 4: User language preferences
        print("\n" + "=" * 80)
        print("Example 4: User Language Preferences")
        print("=" * 80)
        
        # Set preference for user
        user_pref = LanguagePreference(
            primary_language=Language.SPANISH,
            secondary_languages=[Language.ENGLISH],
            regional_variant="es-MX",
            formality_level="formal"
        )
        
        agent.set_user_preference("user123", user_pref)
        
        print("\nUser Preference Set:")
        print(f"  Primary: {user_pref.primary_language.name}")
        print(f"  Variant: {user_pref.regional_variant}")
        print(f"  Formality: {user_pref.formality_level}")
        
        print("\nUser sends message in English:")
        user_msg = "What's the weather like?"
        print(f'User: {user_msg}')
        
        response = agent.respond(user_msg, user_id="user123")
        print(f'Agent (responds in Spanish): {response}')
        
        # Example 5: Code-switching handling
        print("\n" + "=" * 80)
        print("Example 5: Handling Code-Switching")
        print("=" * 80)
        
        mixed_text = "I went to the mercado to buy some légumes and Brot"
        
        print(f'\nMixed-language text: "{mixed_text}"')
        print("(English + Spanish + French + German)")
        
        analysis = agent.handle_mixed_language(mixed_text)
        print("\nAnalysis:")
        print(analysis["analysis"])
        
        # Example 6: Content localization
        print("\n" + "=" * 80)
        print("Example 6: Content Localization")
        print("=" * 80)
        
        us_content = "The conference starts at 9 AM on 12/25. Temperature will be 72°F."
        
        print(f"\nOriginal (US English):")
        print(f"  {us_content}")
        
        print("\nLocalized versions:")
        
        # UK English
        uk_version = agent.localize_content(us_content, Language.ENGLISH, region="UK")
        print(f"\nUK English:")
        print(f"  {uk_version}")
        
        # Spanish (Mexico)
        mx_version = agent.localize_content(us_content, Language.SPANISH, region="MX")
        print(f"\nSpanish (Mexico):")
        print(f"  {mx_version}")
        
        # Example 7: Multilingual customer support
        print("\n" + "=" * 80)
        print("Example 7: Multilingual Customer Support")
        print("=" * 80)
        
        support_queries = [
            ("My order hasn't arrived yet", Language.ENGLISH),
            ("¿Dónde está mi pedido?", Language.SPANISH),
            ("Je n'ai pas reçu ma commande", Language.FRENCH)
        ]
        
        print("\nHandling support queries in multiple languages:")
        
        for query, response_lang in support_queries:
            detected, _ = agent.detect_language(query)
            print(f'\n[{detected.name}] Customer: {query}')
            response = agent.respond(query, target_language=response_lang)
            print(f'[{response_lang.name}] Agent: {response}')
        
        # Example 8: Language statistics
        print("\n" + "=" * 80)
        print("Example 8: Language Usage Statistics")
        print("=" * 80)
        
        stats = agent.get_language_statistics()
        
        print("\nLANGUAGE STATISTICS:")
        print("=" * 60)
        print(f"Total Messages: {stats['total_messages']}")
        print(f"\nLanguages Detected: {', '.join([lang.name for lang in stats['languages_detected']])}")
        
        if stats.get('language_distribution'):
            print("\nDistribution:")
            for lang, count in stats['language_distribution'].items():
                percentage = (count / stats['total_messages']) * 100
                print(f"  {lang}: {count} ({percentage:.1f}%)")
        
        print(f"\nMost Common: {stats['most_common']}")
        
        # Summary
        print("\n" + "=" * 80)
        print("SUMMARY: Polyglot Agent Pattern")
        print("=" * 80)
        
        summary = """
        The Polyglot Agent pattern demonstrated:
        
        1. LANGUAGE DETECTION (Example 1):
           - Automatic identification
           - Confidence scoring
           - Multiple language support
           - Pattern recognition
           - Fallback mechanisms
        
        2. TRANSLATION (Example 2):
           - High-quality conversion
           - Context preservation
           - Multiple target languages
           - Tone maintenance
           - Cultural awareness
        
        3. MULTILINGUAL CONVERSATION (Example 3):
           - Seamless language switching
           - Context preservation
           - Natural flow
           - Automatic adaptation
           - Real-time processing
        
        4. USER PREFERENCES (Example 4):
           - Language preference storage
           - Regional variants
           - Formality levels
           - Automatic application
           - Personalization
        
        5. CODE-SWITCHING (Example 5):
           - Mixed-language handling
           - Language segment identification
           - Dominant language detection
           - Comprehensive translation
           - Context understanding
        
        6. LOCALIZATION (Example 6):
           - Regional adaptation
           - Cultural appropriateness
           - Unit conversion
           - Date format adjustment
           - Idiomatic expressions
        
        7. CUSTOMER SUPPORT (Example 7):
           - Multilingual queries
           - Appropriate responses
           - Language matching
           - Service quality
           - Global reach
        
        8. USAGE ANALYTICS (Example 8):
           - Language distribution
           - Usage patterns
           - Statistics tracking
           - Popular languages
           - Coverage analysis
        
        KEY BENEFITS:
        ✓ Global reach
        ✓ Better user experience
        ✓ Market expansion
        ✓ Cultural inclusivity
        ✓ Reduced translation costs
        ✓ Real-time support
        ✓ Consistent quality
        ✓ Wider accessibility
        
        USE CASES:
        • Global customer support
        • Multilingual content generation
        • International e-commerce
        • Language learning apps
        • Global documentation
        • Multilingual chatbots
        • Business communication
        • Content localization
        
        LANGUAGE CAPABILITIES:
        → Detection: Identify input language
        → Translation: Convert between languages
        → Generation: Create multilingual content
        → Code-Switching: Handle mixed languages
        → Localization: Regional adaptation
        → Transcreation: Cultural adaptation
        → Validation: Quality checking
        
        SUPPORTED FEATURES:
        • Multiple languages (10+)
        • Automatic detection
        • Context awareness
        • Cultural sensitivity
        • Consistent terminology
        • Bidirectional translation
        • Real-time processing
        
        BEST PRACTICES:
        1. Support major languages first
        2. Provide human translation fallback
        3. Track translation quality
        4. Handle rare languages gracefully
        5. Cache common translations
        6. Monitor language coverage
        7. Respect regional preferences
        8. Enable language override
        
        TRADE-OFFS:
        • Coverage vs. quality
        • Speed vs. accuracy
        • Automation vs. human review
        • Generalization vs. specialization
        
        PRODUCTION CONSIDERATIONS:
        → Prioritize high-traffic languages
        → Implement quality monitoring
        → Cache frequent translations
        → Provide confidence scores
        → Enable human escalation
        → Track accuracy metrics
        → Support regional variants
        → Handle cultural sensitivities
        → Maintain terminology consistency
        → Update language models regularly
        
        This pattern enables truly global AI applications that can serve users
        in their native languages while maintaining quality and cultural
        appropriateness across all interactions.
        """
        
        print(summary)
    
    
    if __name__ == "__main__":
        demonstrate_polyglot()
    
        

    Agentic Design Pattern: Polyglot Agent

    Pattern 135: Polyglot Agent – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Polyglot Agent pattern implementation.


    Pattern Description

    Pattern 135: Polyglot Agent

    Description: The Polyglot Agent pattern creates agents capable of understanding and generating content in multiple languages. Unlike single-language agents, polyglot agents can seamlessly switch between languages, translate content, detect language automatically, and maintain context across language boundaries. They understand cultural nuances, idioms, and context-specific language usage.

    Polyglot agents are essential for global applications where users speak different
    languages, content needs translation, or multilingual support is required. They
    go beyond simple translation to understand context, maintain consistency across
    languages, and adapt tone appropriately for different cultures.
    
    This pattern enables truly global AI applications that can serve users in their
    native languages while maintaining quality and coherence across all interactions.
    

    Key Components: 1. Language Detection: Automatic language identification 2. Translation Engine: High-quality translation 3. Context Preservation: Maintain meaning across languages 4. Cultural Adaptation: Culturally appropriate responses 5. Language Memory: Track language preferences 6. Multilingual Knowledge: Language-specific information 7. Quality Validation: Translation accuracy checks

    Language Capabilities: 1. Detection: Identify input language 2. Translation: Convert between languages 3. Generation: Create content in any language 4. Code-Switching: Handle mixed-language input 5. Localization: Adapt to regional variants 6. Transcreation: Culturally adapt content 7. Validation: Check translation quality

    Supported Features: 1. Multiple Languages: Support for many languages 2. Automatic Detection: Identify language without prompting 3. Context Awareness: Understand conversation flow 4. Cultural Sensitivity: Respect cultural differences 5. Consistent Terminology: Maintain vocabulary across languages 6. Bidirectional: Handle any language pair 7. Real-time: Fast language processing

    Use Cases: – Global customer support – Multilingual content generation – International e-commerce – Language learning applications – Global documentation – Multilingual chatbots – International business communication – Content localization

    Advantages: – Global reach – Better user experience – Market expansion – Cultural inclusivity – Reduced translation costs – Real-time multilingual support – Consistent brand voice

    Challenges: – Translation accuracy – Cultural nuances – Idiom handling – Context preservation – Language model quality – Regional variations – Technical terminology

    LangChain Implementation: This implementation uses LangChain for: – Language detection – Translation chains – Multilingual generation – Context tracking

    Production Considerations: – Support major languages first – Provide human translation fallback – Track translation quality – Handle rare languages gracefully – Cache common translations – Monitor language coverage – Respect regional preferences – Enable language selection override


    File Statistics

    • Total Lines: 751
    • Classes: 4
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 135: Polyglot Agent
    
    Description:
        The Polyglot Agent pattern creates agents capable of understanding and
        generating content in multiple languages. Unlike single-language agents,
        polyglot agents can seamlessly switch between languages, translate content,
        detect language automatically, and maintain context across language boundaries.
        They understand cultural nuances, idioms, and context-specific language usage.
    
        Polyglot agents are essential for global applications where users speak different
        languages, content needs translation, or multilingual support is required. They
        go beyond simple translation to understand context, maintain consistency across
        languages, and adapt tone appropriately for different cultures.
    
        This pattern enables truly global AI applications that can serve users in their
        native languages while maintaining quality and coherence across all interactions.
    
    Key Components:
        1. Language Detection: Automatic language identification
        2. Translation Engine: High-quality translation
        3. Context Preservation: Maintain meaning across languages
        4. Cultural Adaptation: Culturally appropriate responses
        5. Language Memory: Track language preferences
        6. Multilingual Knowledge: Language-specific information
        7. Quality Validation: Translation accuracy checks
    
    Language Capabilities:
        1. Detection: Identify input language
        2. Translation: Convert between languages
        3. Generation: Create content in any language
        4. Code-Switching: Handle mixed-language input
        5. Localization: Adapt to regional variants
        6. Transcreation: Culturally adapt content
        7. Validation: Check translation quality
    
    Supported Features:
        1. Multiple Languages: Support for many languages
        2. Automatic Detection: Identify language without prompting
        3. Context Awareness: Understand conversation flow
        4. Cultural Sensitivity: Respect cultural differences
        5. Consistent Terminology: Maintain vocabulary across languages
        6. Bidirectional: Handle any language pair
        7. Real-time: Fast language processing
    
    Use Cases:
        - Global customer support
        - Multilingual content generation
        - International e-commerce
        - Language learning applications
        - Global documentation
        - Multilingual chatbots
        - International business communication
        - Content localization
    
    Advantages:
        - Global reach
        - Better user experience
        - Market expansion
        - Cultural inclusivity
        - Reduced translation costs
        - Real-time multilingual support
        - Consistent brand voice
    
    Challenges:
        - Translation accuracy
        - Cultural nuances
        - Idiom handling
        - Context preservation
        - Language model quality
        - Regional variations
        - Technical terminology
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Language detection
        - Translation chains
        - Multilingual generation
        - Context tracking
    
    Production Considerations:
        - Support major languages first
        - Provide human translation fallback
        - Track translation quality
        - Handle rare languages gracefully
        - Cache common translations
        - Monitor language coverage
        - Respect regional preferences
        - Enable language selection override
    """
    

    Purpose: This module implements the Polyglot Agent pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    import typing.Tuple
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Tuple: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: Language

    Lines 106-120

    Inherits from: Enum

    Purpose:

    Supported languages.
    

    Class: LanguagePreference

    Lines 124-137

    Purpose:

    User language preferences.
    
    Attributes:
        primary_language: Main language
        secondary_languages: Alternative languages
        regional_variant: Regional dialect (e.g., en-US, en-GB)
        formality_level: Formal or informal
    

    Class: MultilingualMessage

    Lines 141-160

    Purpose:

    Message with language information.
    
    Attributes:
        message_id: Unique identifier
        content: Message content
        detected_language: Detected language
        target_language: Desired output language
        translation: Translated content if applicable
        confidence: Language detection confidence
        timestamp: When created
    

    Class: PolyglotAgent

    Lines 163-443

    Purpose:

    Agent with multilingual capabilities.
    
    This agent can understand and generate content in multiple
    languages with context preservation and cultural awareness.
    

    Methods:

    __init__(self, temperature)

    Lines 171-191

    Purpose:

    Initialize polyglot agent.
    
    Args:
        temperature: LLM temperature
    

    Parameters: – temperature: Sampling temperature (0-1)

    detect_language(self, text)

    Lines 193-233

    Purpose:

    Detect language of text.
    
    Args:
        text: Input text
    
    Returns:
        Detected language and confidence
    

    Parameters: – text: Text

    Returns: <ast.Subscript object at 0x000001A06D165BD0>

    translate(self, text, source_language, target_language, context)

    Lines 235-283

    Purpose:

    Translate text between languages.
    
    Args:
        text: Text to translate
        source_language: Source language
        target_language: Target language
        context: Optional context
    
    Returns:
        Translated text
    

    Parameters: – text: Text – source_language: Source language – target_language: Target language – context: Context

    Returns: str

    respond(self, user_input, target_language, user_id)

    Lines 285-342

    Purpose:

    Respond to user in appropriate language.
    
    Args:
        user_input: User's message
        target_language: Desired response language (auto-detect if None)
        user_id: User identifier for preferences
    
    Returns:
        Response in target language
    

    Parameters: – user_input: Input data – target_language: Target language – user_id: User id

    Returns: str

    set_user_preference(self, user_id, preference)

    Lines 344-346

    Purpose:

    Set language preferences for a user.
    

    Parameters: – user_id: User id – preference: Preference

    handle_mixed_language(self, text)

    Lines 348-373

    Purpose:

    Handle text with multiple languages (code-switching).
    
    Args:
        text: Mixed-language text
    
    Returns:
        Analysis of language segments
    

    Parameters: – text: Text

    Returns: <ast.Subscript object at 0x000001A06D85B7D0>

    localize_content(self, content, target_language, region)

    Lines 375-420

    Purpose:

    Localize content for specific language and region.
    
    Args:
        content: Content to localize
        target_language: Target language
        region: Regional variant (e.g., US, UK, BR)
    
    Returns:
        Localized content
    

    Parameters: – content: Content – target_language: Target language – region: Region

    Returns: str

    get_language_statistics(self)

    Lines 422-443

    Purpose:

    Get statistics about language usage.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D7CB110>


    Functions

    demonstrate_polyglot()

    Lines 446-746

    Purpose:

    Demonstrate polyglot agent pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Polyglot Agent pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 134
    • Pattern 136

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Polyglot Agent pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 135_polyglot_agent.py
    Total Lines: 751
    Pattern Category: AI Agent Design Pattern #135


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Task Specific

    
        """
    Pattern 134: Task-Specific Agent
    
    Description:
        The Task-Specific Agent pattern creates agents optimized for particular tasks
        or workflows. Unlike general-purpose agents or domain experts with broad knowledge,
        task-specific agents are highly specialized for executing specific operations with
        maximum efficiency and reliability. They have deep knowledge of task requirements,
        common pitfalls, optimization strategies, and best practices for their specific task.
        
        Task-specific agents excel at their designated task through specialized prompts,
        optimized workflows, task-specific tools, relevant examples, and failure handling
        tailored to common task issues. They sacrifice breadth for depth, becoming experts
        at their single task rather than generalists.
        
        This pattern is essential for production systems where certain tasks are performed
        repeatedly and require consistent, high-quality execution. Examples include data
        validation agents, report generation agents, code review agents, content moderation
        agents, and translation agents.
    
    Key Components:
        1. Task Definition: Clear specification of the task
        2. Optimized Workflow: Step-by-step task execution
        3. Task-Specific Tools: Specialized utilities
        4. Example Repository: Reference cases
        5. Validation Logic: Task-specific quality checks
        6. Error Handling: Common failure patterns
        7. Performance Metrics: Task success criteria
    
    Task Specialization:
        1. Single Responsibility: One task, done well
        2. Optimized Prompts: Tailored to task requirements
        3. Specialized Tools: Task-specific utilities
        4. Domain Knowledge: Deep task understanding
        5. Workflow Efficiency: Streamlined execution
        6. Error Recovery: Task-specific failure handling
        7. Quality Assurance: Task validation
    
    Task Categories:
        1. Data Processing: Validation, transformation, cleaning
        2. Content Generation: Reports, summaries, descriptions
        3. Analysis: Code review, sentiment analysis, quality assessment
        4. Transformation: Translation, format conversion, restructuring
        5. Validation: Compliance checking, verification, testing
        6. Interaction: Onboarding, support, guidance
        7. Monitoring: Alert processing, anomaly detection
    
    Use Cases:
        - Data validation and cleaning
        - Automated report generation
        - Code review and analysis
        - Content moderation
        - Language translation
        - Email response generation
        - Invoice processing
        - Resume screening
    
    Advantages:
        - Maximum task efficiency
        - Consistent quality
        - Deep task optimization
        - Reduced error rates
        - Fast execution
        - Reliable performance
        - Easy to test and validate
    
    Challenges:
        - Limited flexibility
        - Task scope creep
        - Adaptation to task changes
        - Over-optimization risk
        - Maintenance overhead
        - Integration complexity
        - Version management
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Task-optimized prompts
        - Specialized tool chains
        - Validation pipelines
        - Performance tracking
        
    Production Considerations:
        - Version task-specific agents
        - Monitor task success rates
        - Track execution time
        - Log validation failures
        - Implement rollback mechanisms
        - A/B test task variations
        - Collect user feedback
        - Maintain task documentation
    """
    
    import os
    from typing import List, Dict, Any, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class TaskStatus(Enum):
        """Task execution status."""
        PENDING = "pending"
        IN_PROGRESS = "in_progress"
        COMPLETED = "completed"
        FAILED = "failed"
        VALIDATED = "validated"
    
    
    class ValidationResult(Enum):
        """Validation outcome."""
        PASSED = "passed"
        FAILED = "failed"
        WARNING = "warning"
    
    
    @dataclass
    class TaskSpecification:
        """
        Specification for a task.
        
        Attributes:
            task_name: Name of the task
            description: Task description
            inputs: Required input fields
            outputs: Expected output fields
            validation_rules: Rules to validate outputs
            examples: Example inputs and outputs
            success_criteria: What defines success
            common_failures: Known failure patterns
        """
        task_name: str
        description: str
        inputs: List[str] = field(default_factory=list)
        outputs: List[str] = field(default_factory=list)
        validation_rules: List[str] = field(default_factory=list)
        examples: List[Dict[str, Any]] = field(default_factory=list)
        success_criteria: List[str] = field(default_factory=list)
        common_failures: List[str] = field(default_factory=list)
    
    
    @dataclass
    class TaskExecution:
        """
        Record of task execution.
        
        Attributes:
            execution_id: Unique identifier
            task_name: Name of executed task
            inputs: Input data
            outputs: Generated outputs
            status: Execution status
            validation: Validation results
            duration_seconds: Execution time
            errors: Any errors encountered
            timestamp: When executed
        """
        execution_id: str
        task_name: str
        inputs: Dict[str, Any]
        outputs: Dict[str, Any] = field(default_factory=dict)
        status: TaskStatus = TaskStatus.PENDING
        validation: Optional[ValidationResult] = None
        duration_seconds: float = 0.0
        errors: List[str] = field(default_factory=list)
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class TaskSpecificAgent:
        """
        Agent specialized for a specific task.
        
        This agent is optimized for executing a single task
        with maximum efficiency and reliability.
        """
        
        def __init__(
            self,
            task_spec: TaskSpecification,
            temperature: float = 0.3
        ):
            """
            Initialize task-specific agent.
            
            Args:
                task_spec: Task specification
                temperature: LLM temperature (lower for consistency)
            """
            self.task_spec = task_spec
            self.llm = ChatOpenAI(temperature=temperature, model="gpt-3.5-turbo")
            self.execution_history: List[TaskExecution] = []
            self.execution_counter = 0
        
        def _build_task_prompt(self, inputs: Dict[str, Any]) -> str:
            """Build optimized prompt for task."""
            prompt_parts = [
                f"Task: {self.task_spec.task_name}",
                f"Description: {self.task_spec.description}",
                ""
            ]
            
            # Add success criteria
            if self.task_spec.success_criteria:
                criteria = "\n".join([f"  - {c}" for c in self.task_spec.success_criteria])
                prompt_parts.append(f"Success Criteria:\n{criteria}\n")
            
            # Add examples
            if self.task_spec.examples:
                prompt_parts.append("Examples:")
                for i, example in enumerate(self.task_spec.examples[:2], 1):
                    prompt_parts.append(f"\nExample {i}:")
                    prompt_parts.append(f"  Input: {example.get('input', 'N/A')}")
                    prompt_parts.append(f"  Output: {example.get('output', 'N/A')}")
                prompt_parts.append("")
            
            # Add common failures to avoid
            if self.task_spec.common_failures:
                failures = "\n".join([f"  - {f}" for f in self.task_spec.common_failures])
                prompt_parts.append(f"Avoid These Common Mistakes:\n{failures}\n")
            
            # Add current input
            prompt_parts.append("Current Input:")
            for key, value in inputs.items():
                prompt_parts.append(f"  {key}: {value}")
            
            prompt_parts.append("\nExecute the task and provide the output:")
            
            return "\n".join(prompt_parts)
        
        def execute(self, inputs: Dict[str, Any]) -> TaskExecution:
            """
            Execute the task.
            
            Args:
                inputs: Task inputs
                
            Returns:
                Task execution record
            """
            self.execution_counter += 1
            execution = TaskExecution(
                execution_id=f"exec_{self.execution_counter}",
                task_name=self.task_spec.task_name,
                inputs=inputs,
                status=TaskStatus.IN_PROGRESS
            )
            
            start_time = datetime.now()
            
            try:
                # Build prompt
                task_prompt = self._build_task_prompt(inputs)
                
                # Execute task
                prompt = ChatPromptTemplate.from_template("{task_prompt}")
                chain = prompt | self.llm | StrOutputParser()
                
                output_text = chain.invoke({"task_prompt": task_prompt})
                
                # Parse outputs
                outputs = self._parse_output(output_text)
                execution.outputs = outputs
                execution.status = TaskStatus.COMPLETED
                
            except Exception as e:
                execution.status = TaskStatus.FAILED
                execution.errors.append(str(e))
            
            # Calculate duration
            execution.duration_seconds = (datetime.now() - start_time).total_seconds()
            
            # Store execution
            self.execution_history.append(execution)
            
            return execution
        
        def _parse_output(self, output_text: str) -> Dict[str, Any]:
            """Parse output from text response."""
            # Simple parsing - in production, use structured output
            outputs = {"raw_output": output_text}
            
            # Try to extract key-value pairs
            lines = output_text.split('\n')
            for line in lines:
                if ':' in line:
                    parts = line.split(':', 1)
                    if len(parts) == 2:
                        key = parts[0].strip().lower().replace(' ', '_')
                        value = parts[1].strip()
                        outputs[key] = value
            
            return outputs
        
        def validate(self, execution: TaskExecution) -> ValidationResult:
            """
            Validate task execution.
            
            Args:
                execution: Execution to validate
                
            Returns:
                Validation result
            """
            if execution.status != TaskStatus.COMPLETED:
                execution.validation = ValidationResult.FAILED
                return ValidationResult.FAILED
            
            # Check required outputs
            missing_outputs = []
            for required_output in self.task_spec.outputs:
                if required_output not in execution.outputs:
                    missing_outputs.append(required_output)
            
            if missing_outputs:
                execution.errors.append(f"Missing outputs: {missing_outputs}")
                execution.validation = ValidationResult.FAILED
                return ValidationResult.FAILED
            
            # Apply validation rules using LLM
            if self.task_spec.validation_rules:
                validation_prompt = (
                    f"Validate this task output:\n\n"
                    f"Task: {self.task_spec.task_name}\n"
                    f"Output: {execution.outputs}\n\n"
                    f"Validation Rules:\n"
                )
                for rule in self.task_spec.validation_rules:
                    validation_prompt += f"- {rule}\n"
                
                validation_prompt += "\nDoes the output pass validation? Respond with PASSED, FAILED, or WARNING."
                
                prompt = ChatPromptTemplate.from_template("{validation_prompt}")
                chain = prompt | self.llm | StrOutputParser()
                
                result_text = chain.invoke({"validation_prompt": validation_prompt})
                
                if "PASSED" in result_text.upper():
                    execution.validation = ValidationResult.PASSED
                    execution.status = TaskStatus.VALIDATED
                    return ValidationResult.PASSED
                elif "WARNING" in result_text.upper():
                    execution.validation = ValidationResult.WARNING
                    return ValidationResult.WARNING
                else:
                    execution.validation = ValidationResult.FAILED
                    return ValidationResult.FAILED
            
            # Default to passed if no rules
            execution.validation = ValidationResult.PASSED
            execution.status = TaskStatus.VALIDATED
            return ValidationResult.PASSED
        
        def execute_and_validate(self, inputs: Dict[str, Any]) -> TaskExecution:
            """Execute task and validate result."""
            execution = self.execute(inputs)
            self.validate(execution)
            return execution
        
        def get_performance_metrics(self) -> Dict[str, Any]:
            """Get task performance metrics."""
            if not self.execution_history:
                return {
                    "total_executions": 0,
                    "success_rate": 0.0,
                    "validation_rate": 0.0,
                    "avg_duration": 0.0
                }
            
            total = len(self.execution_history)
            completed = sum(1 for e in self.execution_history if e.status == TaskStatus.COMPLETED)
            validated = sum(1 for e in self.execution_history if e.validation == ValidationResult.PASSED)
            
            total_duration = sum(e.duration_seconds for e in self.execution_history)
            
            return {
                "total_executions": total,
                "success_rate": completed / total if total > 0 else 0.0,
                "validation_rate": validated / total if total > 0 else 0.0,
                "avg_duration": total_duration / total if total > 0 else 0.0,
                "task_name": self.task_spec.task_name
            }
    
    
    def demonstrate_task_specific():
        """Demonstrate task-specific agent pattern."""
        
        print("=" * 80)
        print("TASK-SPECIFIC AGENT PATTERN DEMONSTRATION")
        print("=" * 80)
        
        # Example 1: Email Response Task
        print("\n" + "=" * 80)
        print("Example 1: Email Response Generation Task")
        print("=" * 80)
        
        email_task = TaskSpecification(
            task_name="Customer Support Email Response",
            description="Generate professional customer support email responses",
            inputs=["customer_email", "issue_type", "customer_name"],
            outputs=["subject", "body", "tone"],
            validation_rules=[
                "Response must be polite and professional",
                "Must address the customer by name",
                "Must include a clear solution or next steps",
                "Must be under 200 words"
            ],
            examples=[
                {
                    "input": {
                        "customer_email": "My order hasn't arrived",
                        "issue_type": "shipping_delay",
                        "customer_name": "John"
                    },
                    "output": {
                        "subject": "Update on Your Order Status",
                        "body": "Dear John, I apologize for the delay...",
                        "tone": "empathetic and solution-focused"
                    }
                }
            ],
            success_criteria=[
                "Customer feels heard and valued",
                "Clear action items provided",
                "Professional tone maintained"
            ],
            common_failures=[
                "Being too formal or robotic",
                "Not acknowledging the customer's frustration",
                "Providing vague next steps"
            ]
        )
        
        email_agent = TaskSpecificAgent(email_task)
        
        print(f"\nTask: {email_task.task_name}")
        print(f"Description: {email_task.description}")
        print(f"Required Inputs: {', '.join(email_task.inputs)}")
        print(f"Expected Outputs: {', '.join(email_task.outputs)}")
        
        # Example 2: Execute task
        print("\n" + "=" * 80)
        print("Example 2: Task Execution")
        print("=" * 80)
        
        customer_input = {
            "customer_email": "I'm frustrated! My package was supposed to arrive 3 days ago!",
            "issue_type": "shipping_delay",
            "customer_name": "Sarah"
        }
        
        print("\nInput:")
        for key, value in customer_input.items():
            print(f"  {key}: {value}")
        
        execution = email_agent.execute(customer_input)
        
        print(f"\nExecution Status: {execution.status.value}")
        print(f"Duration: {execution.duration_seconds:.2f}s")
        print("\nGenerated Output:")
        for key, value in execution.outputs.items():
            if key != "raw_output":
                print(f"  {key}: {value}")
        
        # Example 3: Validation
        print("\n" + "=" * 80)
        print("Example 3: Output Validation")
        print("=" * 80)
        
        validation_result = email_agent.validate(execution)
        
        print(f"\nValidation Result: {validation_result.value}")
        print(f"Final Status: {execution.status.value}")
        
        if execution.errors:
            print(f"Errors: {execution.errors}")
        
        # Example 4: Data Validation Task
        print("\n" + "=" * 80)
        print("Example 4: Data Validation Task")
        print("=" * 80)
        
        validation_task = TaskSpecification(
            task_name="User Registration Data Validation",
            description="Validate user registration data for completeness and correctness",
            inputs=["email", "username", "age", "country"],
            outputs=["is_valid", "errors", "warnings"],
            validation_rules=[
                "Email must be valid format",
                "Username must be 3-20 characters",
                "Age must be 18 or older",
                "Country must be a valid country code"
            ],
            success_criteria=[
                "All validation rules checked",
                "Clear error messages provided",
                "Actionable feedback given"
            ],
            common_failures=[
                "Missing validation checks",
                "Vague error messages",
                "Not checking all fields"
            ]
        )
        
        validator_agent = TaskSpecificAgent(validation_task, temperature=0.1)
        
        print(f"\nTask: {validation_task.task_name}")
        
        # Valid data
        valid_data = {
            "email": "user@example.com",
            "username": "johndoe",
            "age": "25",
            "country": "US"
        }
        
        print("\nValidating Valid Data:")
        print(f"  {valid_data}")
        
        execution1 = validator_agent.execute_and_validate(valid_data)
        print(f"Result: {execution1.validation.value if execution1.validation else 'N/A'}")
        
        # Invalid data
        invalid_data = {
            "email": "not-an-email",
            "username": "ab",
            "age": "15",
            "country": "XYZ"
        }
        
        print("\nValidating Invalid Data:")
        print(f"  {invalid_data}")
        
        execution2 = validator_agent.execute_and_validate(invalid_data)
        print(f"Result: {execution2.validation.value if execution2.validation else 'N/A'}")
        
        # Example 5: Code Review Task
        print("\n" + "=" * 80)
        print("Example 5: Code Review Task")
        print("=" * 80)
        
        code_review_task = TaskSpecification(
            task_name="Python Code Review",
            description="Review Python code for quality, security, and best practices",
            inputs=["code", "context"],
            outputs=["issues", "suggestions", "severity", "approval"],
            validation_rules=[
                "Must identify security issues",
                "Must check for best practices",
                "Must provide actionable feedback"
            ],
            success_criteria=[
                "All major issues identified",
                "Suggestions are specific",
                "Severity levels assigned"
            ]
        )
        
        reviewer_agent = TaskSpecificAgent(code_review_task)
        
        code_sample = """
    def process_user_input(input):
        result = eval(input)  # Security issue!
        return result
    """
        
        print(f"\nReviewing Code:")
        print(code_sample)
        
        review_execution = reviewer_agent.execute({
            "code": code_sample,
            "context": "User input processing function"
        })
        
        print(f"\nReview Status: {review_execution.status.value}")
        print("Review Output:")
        print(review_execution.outputs.get("raw_output", "No output")[:500])
        
        # Example 6: Performance metrics
        print("\n" + "=" * 80)
        print("Example 6: Task Performance Metrics")
        print("=" * 80)
        
        # Execute multiple tasks
        test_inputs = [
            {"customer_email": "Test 1", "issue_type": "general", "customer_name": "User1"},
            {"customer_email": "Test 2", "issue_type": "technical", "customer_name": "User2"},
            {"customer_email": "Test 3", "issue_type": "billing", "customer_name": "User3"}
        ]
        
        for inputs in test_inputs:
            email_agent.execute_and_validate(inputs)
        
        metrics = email_agent.get_performance_metrics()
        
        print("\nPERFORMANCE METRICS:")
        print("=" * 60)
        print(f"Task: {metrics['task_name']}")
        print(f"Total Executions: {metrics['total_executions']}")
        print(f"Success Rate: {metrics['success_rate']:.1%}")
        print(f"Validation Rate: {metrics['validation_rate']:.1%}")
        print(f"Average Duration: {metrics['avg_duration']:.2f}s")
        
        # Example 7: Translation Task
        print("\n" + "=" * 80)
        print("Example 7: Translation Task")
        print("=" * 80)
        
        translation_task = TaskSpecification(
            task_name="English to Spanish Translation",
            description="Translate English text to Spanish maintaining tone and context",
            inputs=["english_text", "context"],
            outputs=["spanish_text", "confidence"],
            validation_rules=[
                "Translation must preserve meaning",
                "Must maintain appropriate tone",
                "Must be grammatically correct"
            ],
            success_criteria=[
                "Accurate translation",
                "Natural Spanish phrasing",
                "Context-appropriate"
            ]
        )
        
        translator = TaskSpecificAgent(translation_task)
        
        translation_input = {
            "english_text": "Hello, how can I help you today?",
            "context": "Customer service greeting"
        }
        
        print("\nTranslation Input:")
        print(f"  Text: {translation_input['english_text']}")
        print(f"  Context: {translation_input['context']}")
        
        translation_result = translator.execute_and_validate(translation_input)
        print(f"\nTranslation Status: {translation_result.status.value}")
        print("Translation Output:")
        for key, value in translation_result.outputs.items():
            if key != "raw_output":
                print(f"  {key}: {value}")
        
        # Example 8: Summary task
        print("\n" + "=" * 80)
        print("Example 8: Task Agent Summary")
        print("=" * 80)
        
        print("\nDEPLOYED TASK-SPECIFIC AGENTS:")
        print("=" * 60)
        
        agents_summary = [
            ("Email Response", email_agent),
            ("Data Validation", validator_agent),
            ("Code Review", reviewer_agent),
            ("Translation", translator)
        ]
        
        for name, agent in agents_summary:
            metrics = agent.get_performance_metrics()
            print(f"\n{name}:")
            print(f"  Executions: {metrics['total_executions']}")
            print(f"  Success Rate: {metrics['success_rate']:.1%}")
            print(f"  Avg Duration: {metrics['avg_duration']:.2f}s")
        
        # Summary
        print("\n" + "=" * 80)
        print("SUMMARY: Task-Specific Agent Pattern")
        print("=" * 80)
        
        summary = """
        The Task-Specific Agent pattern demonstrated:
        
        1. TASK SPECIALIZATION (Example 1):
           - Single-purpose agents
           - Optimized for specific tasks
           - Task-specific prompts
           - Validation rules
           - Success criteria
           - Common failure awareness
        
        2. TASK EXECUTION (Example 2):
           - Optimized workflow
           - Input processing
           - Output generation
           - Performance tracking
           - Status monitoring
        
        3. OUTPUT VALIDATION (Example 3):
           - Rule-based validation
           - Required output checking
           - Quality assurance
           - Error detection
           - Validation feedback
        
        4. DATA VALIDATION TASK (Example 4):
           - Field validation
           - Format checking
           - Business rule enforcement
           - Error reporting
           - Actionable feedback
        
        5. CODE REVIEW TASK (Example 5):
           - Security analysis
           - Best practice checking
           - Issue identification
           - Severity assessment
           - Specific suggestions
        
        6. PERFORMANCE TRACKING (Example 6):
           - Execution metrics
           - Success rates
           - Duration monitoring
           - Quality metrics
           - Continuous improvement
        
        7. TRANSLATION TASK (Example 7):
           - Language conversion
           - Context preservation
           - Tone maintenance
           - Accuracy validation
           - Confidence scoring
        
        8. MULTI-TASK DEPLOYMENT (Example 8):
           - Multiple specialized agents
           - Independent optimization
           - Performance comparison
           - Resource allocation
           - System overview
        
        KEY BENEFITS:
        ✓ Maximum task efficiency
        ✓ Consistent quality
        ✓ Deep optimization
        ✓ Reduced errors
        ✓ Fast execution
        ✓ Reliable performance
        ✓ Easy testing
        ✓ Clear metrics
        
        USE CASES:
        • Data validation and cleaning
        • Automated report generation
        • Code review and analysis
        • Content moderation
        • Language translation
        • Email response generation
        • Invoice processing
        • Resume screening
        
        TASK CATEGORIES:
        → Data Processing: Validation, transformation
        → Content Generation: Reports, summaries
        → Analysis: Code review, quality assessment
        → Transformation: Translation, conversion
        → Validation: Compliance, verification
        → Interaction: Support, guidance
        → Monitoring: Alerts, anomaly detection
        
        SPECIALIZATION ASPECTS:
        • Single responsibility principle
        • Optimized prompts
        • Specialized tools
        • Domain knowledge
        • Workflow efficiency
        • Error recovery
        • Quality assurance
        
        BEST PRACTICES:
        1. Define clear task boundaries
        2. Optimize for single task
        3. Include comprehensive examples
        4. Implement thorough validation
        5. Track performance metrics
        6. Handle common failures
        7. Version control task specs
        8. Document expected behaviors
        
        TRADE-OFFS:
        • Specialization vs. flexibility
        • Efficiency vs. adaptability
        • Depth vs. breadth
        • Optimization vs. generalization
        
        PRODUCTION CONSIDERATIONS:
        → Version task agents independently
        → Monitor success rates per task
        → Track execution times
        → Log validation failures
        → Implement rollback capabilities
        → A/B test task variations
        → Collect user feedback
        → Maintain task documentation
        → Set performance SLAs
        → Enable task composition
        
        This pattern enables highly efficient, reliable execution of specific tasks
        by sacrificing generality for optimization, resulting in production-grade
        agents that excel at their designated operations.
        """
        
        print(summary)
    
    
    if __name__ == "__main__":
        demonstrate_task_specific()
    
        

    Agentic Design Pattern: Task Specific

    Pattern 134: Task Specific – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Task Specific pattern implementation.


    Pattern Description

    Pattern 134: Task-Specific Agent

    Description: The Task-Specific Agent pattern creates agents optimized for particular tasks or workflows. Unlike general-purpose agents or domain experts with broad knowledge, task-specific agents are highly specialized for executing specific operations with maximum efficiency and reliability. They have deep knowledge of task requirements, common pitfalls, optimization strategies, and best practices for their specific task.

    Task-specific agents excel at their designated task through specialized prompts,
    optimized workflows, task-specific tools, relevant examples, and failure handling
    tailored to common task issues. They sacrifice breadth for depth, becoming experts
    at their single task rather than generalists.
    
    This pattern is essential for production systems where certain tasks are performed
    repeatedly and require consistent, high-quality execution. Examples include data
    validation agents, report generation agents, code review agents, content moderation
    agents, and translation agents.
    

    Key Components: 1. Task Definition: Clear specification of the task 2. Optimized Workflow: Step-by-step task execution 3. Task-Specific Tools: Specialized utilities 4. Example Repository: Reference cases 5. Validation Logic: Task-specific quality checks 6. Error Handling: Common failure patterns 7. Performance Metrics: Task success criteria

    Task Specialization: 1. Single Responsibility: One task, done well 2. Optimized Prompts: Tailored to task requirements 3. Specialized Tools: Task-specific utilities 4. Domain Knowledge: Deep task understanding 5. Workflow Efficiency: Streamlined execution 6. Error Recovery: Task-specific failure handling 7. Quality Assurance: Task validation

    Task Categories: 1. Data Processing: Validation, transformation, cleaning 2. Content Generation: Reports, summaries, descriptions 3. Analysis: Code review, sentiment analysis, quality assessment 4. Transformation: Translation, format conversion, restructuring 5. Validation: Compliance checking, verification, testing 6. Interaction: Onboarding, support, guidance 7. Monitoring: Alert processing, anomaly detection

    Use Cases: – Data validation and cleaning – Automated report generation – Code review and analysis – Content moderation – Language translation – Email response generation – Invoice processing – Resume screening

    Advantages: – Maximum task efficiency – Consistent quality – Deep task optimization – Reduced error rates – Fast execution – Reliable performance – Easy to test and validate

    Challenges: – Limited flexibility – Task scope creep – Adaptation to task changes – Over-optimization risk – Maintenance overhead – Integration complexity – Version management

    LangChain Implementation: This implementation uses LangChain for: – Task-optimized prompts – Specialized tool chains – Validation pipelines – Performance tracking

    Production Considerations: – Version task-specific agents – Monitor task success rates – Track execution time – Log validation failures – Implement rollback mechanisms – A/B test task variations – Collect user feedback – Maintain task documentation


    File Statistics

    • Total Lines: 814
    • Classes: 5
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 134: Task-Specific Agent
    
    Description:
        The Task-Specific Agent pattern creates agents optimized for particular tasks
        or workflows. Unlike general-purpose agents or domain experts with broad knowledge,
        task-specific agents are highly specialized for executing specific operations with
        maximum efficiency and reliability. They have deep knowledge of task requirements,
        common pitfalls, optimization strategies, and best practices for their specific task.
    
        Task-specific agents excel at their designated task through specialized prompts,
        optimized workflows, task-specific tools, relevant examples, and failure handling
        tailored to common task issues. They sacrifice breadth for depth, becoming experts
        at their single task rather than generalists.
    
        This pattern is essential for production systems where certain tasks are performed
        repeatedly and require consistent, high-quality execution. Examples include data
        validation agents, report generation agents, code review agents, content moderation
        agents, and translation agents.
    
    Key Components:
        1. Task Definition: Clear specification of the task
        2. Optimized Workflow: Step-by-step task execution
        3. Task-Specific Tools: Specialized utilities
        4. Example Repository: Reference cases
        5. Validation Logic: Task-specific quality checks
        6. Error Handling: Common failure patterns
        7. Performance Metrics: Task success criteria
    
    Task Specialization:
        1. Single Responsibility: One task, done well
        2. Optimized Prompts: Tailored to task requirements
        3. Specialized Tools: Task-specific utilities
        4. Domain Knowledge: Deep task understanding
        5. Workflow Efficiency: Streamlined execution
        6. Error Recovery: Task-specific failure handling
        7. Quality Assurance: Task validation
    
    Task Categories:
        1. Data Processing: Validation, transformation, cleaning
        2. Content Generation: Reports, summaries, descriptions
        3. Analysis: Code review, sentiment analysis, quality assessment
        4. Transformation: Translation, format conversion, restructuring
        5. Validation: Compliance checking, verification, testing
        6. Interaction: Onboarding, support, guidance
        7. Monitoring: Alert processing, anomaly detection
    
    Use Cases:
        - Data validation and cleaning
        - Automated report generation
        - Code review and analysis
        - Content moderation
        - Language translation
        - Email response generation
        - Invoice processing
        - Resume screening
    
    Advantages:
        - Maximum task efficiency
        - Consistent quality
        - Deep task optimization
        - Reduced error rates
        - Fast execution
        - Reliable performance
        - Easy to test and validate
    
    Challenges:
        - Limited flexibility
        - Task scope creep
        - Adaptation to task changes
        - Over-optimization risk
        - Maintenance overhead
        - Integration complexity
        - Version management
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Task-optimized prompts
        - Specialized tool chains
        - Validation pipelines
        - Performance tracking
    
    Production Considerations:
        - Version task-specific agents
        - Monitor task success rates
        - Track execution time
        - Log validation failures
        - Implement rollback mechanisms
        - A/B test task variations
        - Collect user feedback
        - Maintain task documentation
    """
    

    Purpose: This module implements the Task Specific pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Callable
    import typing.Dict
    import typing.List
    import typing.Optional
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Callable: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: TaskStatus

    Lines 108-114

    Inherits from: Enum

    Purpose:

    Task execution status.
    

    Class: ValidationResult

    Lines 117-121

    Inherits from: Enum

    Purpose:

    Validation outcome.
    

    Class: TaskSpecification

    Lines 125-146

    Purpose:

    Specification for a task.
    
    Attributes:
        task_name: Name of the task
        description: Task description
        inputs: Required input fields
        outputs: Expected output fields
        validation_rules: Rules to validate outputs
        examples: Example inputs and outputs
        success_criteria: What defines success
        common_failures: Known failure patterns
    

    Class: TaskExecution

    Lines 150-173

    Purpose:

    Record of task execution.
    
    Attributes:
        execution_id: Unique identifier
        task_name: Name of executed task
        inputs: Input data
        outputs: Generated outputs
        status: Execution status
        validation: Validation results
        duration_seconds: Execution time
        errors: Any errors encountered
        timestamp: When executed
    

    Class: TaskSpecificAgent

    Lines 176-388

    Purpose:

    Agent specialized for a specific task.
    
    This agent is optimized for executing a single task
    with maximum efficiency and reliability.
    

    Methods:

    __init__(self, task_spec, temperature)

    Lines 184-199

    Purpose:

    Initialize task-specific agent.
    
    Args:
        task_spec: Task specification
        temperature: LLM temperature (lower for consistency)
    

    Parameters: – task_spec: Task spec – temperature: Sampling temperature (0-1)

    _build_task_prompt(self, inputs)

    Lines 201-235

    Purpose:

    Build optimized prompt for task.
    

    Parameters: – inputs: Input data

    Returns: str

    execute(self, inputs)

    Lines 237-282

    Purpose:

    Execute the task.
    
    Args:
        inputs: Task inputs
    
    Returns:
        Task execution record
    

    Parameters: – inputs: Input data

    Returns: TaskExecution

    _parse_output(self, output_text)

    Lines 284-299

    Purpose:

    Parse output from text response.
    

    Parameters: – output_text: Output text

    Returns: <ast.Subscript object at 0x000001A06D68DB90>

    validate(self, execution)

    Lines 301-358

    Purpose:

    Validate task execution.
    
    Args:
        execution: Execution to validate
    
    Returns:
        Validation result
    

    Parameters: – execution: Execution

    Returns: ValidationResult

    execute_and_validate(self, inputs)

    Lines 360-364

    Purpose:

    Execute task and validate result.
    

    Parameters: – inputs: Input data

    Returns: TaskExecution

    get_performance_metrics(self)

    Lines 366-388

    Purpose:

    Get task performance metrics.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D7BA950>


    Functions

    demonstrate_task_specific()

    Lines 391-809

    Purpose:

    Demonstrate task-specific agent pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Task Specific pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 133
    • Pattern 135

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Task Specific pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 134_task_specific.py
    Total Lines: 814
    Pattern Category: AI Agent Design Pattern #134


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Domain Expert

    
        """
    Pattern 133: Domain Expert Agent
    
    Description:
        The Domain Expert Agent pattern creates specialized agents with deep expertise
        in specific domains or fields. Unlike general-purpose agents, domain experts
        possess comprehensive knowledge, terminology, methodologies, and best practices
        specific to their area of specialization. They can provide expert-level advice,
        perform domain-specific reasoning, and apply specialized knowledge effectively.
        
        Domain expertise goes beyond simple knowledge retrieval - it includes understanding
        domain-specific workflows, recognizing patterns, applying heuristics, knowing
        what questions to ask, and understanding the nuances and edge cases within the
        domain. Expert agents can explain complex concepts using domain terminology,
        evaluate solutions using domain-specific criteria, and provide guidance that
        reflects years of accumulated expertise.
        
        This pattern is essential for applications requiring specialized knowledge such
        as medical diagnosis assistants, legal advisors, financial analysts, scientific
        research assistants, engineering consultants, and other professional AI systems.
    
    Key Components:
        1. Domain Knowledge Base: Comprehensive domain-specific information
        2. Terminology Handler: Domain-specific vocabulary and jargon
        3. Best Practices Repository: Field-standard methodologies
        4. Case History: Examples and precedents from the domain
        5. Reasoning Engine: Domain-specific logic and heuristics
        6. Validation System: Domain-appropriate quality checks
        7. Reference System: Citations and sources
    
    Domain Characteristics:
        1. Depth: Comprehensive coverage of specialized area
        2. Terminology: Field-specific vocabulary
        3. Methodology: Domain-standard approaches
        4. Context: Understanding of domain landscape
        5. Precedents: Historical cases and examples
        6. Standards: Industry regulations and best practices
        7. Boundaries: Knowing limits of expertise
    
    Expert Behaviors:
        1. Ask clarifying questions
        2. Identify missing information
        3. Consider edge cases
        4. Reference standards and regulations
        5. Explain reasoning process
        6. Acknowledge uncertainty
        7. Provide multiple perspectives
        8. Use appropriate terminology
    
    Use Cases:
        - Medical diagnosis assistants
        - Legal research and advisory
        - Financial analysis and planning
        - Engineering design consultation
        - Scientific research assistance
        - Tax preparation and planning
        - Architectural design
        - Software architecture advisory
    
    Advantages:
        - Expert-level guidance
        - Domain-appropriate reasoning
        - Specialized knowledge application
        - Professional terminology usage
        - Best practice adherence
        - Quality assurance
        - Credible advice
    
    Challenges:
        - Knowledge maintenance and updates
        - Handling edge cases
        - Avoiding overconfidence
        - Managing liability concerns
        - Balancing depth vs. accessibility
        - Keeping current with field changes
        - Regulatory compliance
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Domain knowledge integration
        - Expert reasoning chains
        - Specialized RAG with domain documents
        - Domain-specific validation
        
    Production Considerations:
        - Regularly update domain knowledge
        - Version control expert systems
        - Track expert vs. actual outcomes
        - Implement human expert review
        - Include disclaimers appropriately
        - Maintain audit trails
        - Ensure regulatory compliance
        - Support expert override mechanisms
    """
    
    import os
    from typing import List, Dict, Any, Optional, Tuple
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class ExpertiseLevel(Enum):
        """Level of expertise."""
        NOVICE = "novice"
        INTERMEDIATE = "intermediate"
        ADVANCED = "advanced"
        EXPERT = "expert"
        MASTER = "master"
    
    
    class ConfidenceLevel(Enum):
        """Confidence in response."""
        LOW = "low"
        MEDIUM = "medium"
        HIGH = "high"
        VERY_HIGH = "very_high"
    
    
    @dataclass
    class DomainKnowledge:
        """
        Domain-specific knowledge item.
        
        Attributes:
            topic: Knowledge area
            content: Information content
            source: Where knowledge came from
            reliability: How reliable (0-1)
            last_updated: When last verified
            tags: Categorization tags
        """
        topic: str
        content: str
        source: str = "expert_knowledge"
        reliability: float = 0.9
        last_updated: datetime = field(default_factory=datetime.now)
        tags: List[str] = field(default_factory=list)
    
    
    @dataclass
    class ExpertResponse:
        """
        Expert agent response.
        
        Attributes:
            answer: Main response
            confidence: Confidence level
            reasoning: Explanation of reasoning
            references: Supporting sources
            caveats: Important limitations or warnings
            follow_up_questions: Suggested clarifications
            alternatives: Alternative approaches
        """
        answer: str
        confidence: ConfidenceLevel
        reasoning: str = ""
        references: List[str] = field(default_factory=list)
        caveats: List[str] = field(default_factory=list)
        follow_up_questions: List[str] = field(default_factory=list)
        alternatives: List[str] = field(default_factory=list)
    
    
    @dataclass
    class DomainExpertise:
        """
        Definition of domain expertise.
        
        Attributes:
            domain_name: Name of domain
            description: Domain description
            expertise_areas: Specific areas of expertise
            methodologies: Standard approaches
            key_concepts: Important domain concepts
            terminology: Domain-specific vocabulary
            standards: Relevant standards and regulations
            common_issues: Frequently encountered problems
            best_practices: Field best practices
        """
        domain_name: str
        description: str
        expertise_areas: List[str] = field(default_factory=list)
        methodologies: List[str] = field(default_factory=list)
        key_concepts: Dict[str, str] = field(default_factory=dict)
        terminology: Dict[str, str] = field(default_factory=dict)
        standards: List[str] = field(default_factory=list)
        common_issues: List[str] = field(default_factory=list)
        best_practices: List[str] = field(default_factory=list)
    
    
    class DomainExpertAgent:
        """
        Agent with specialized domain expertise.
        
        This agent provides expert-level guidance in a specific domain,
        using specialized knowledge, terminology, and reasoning.
        """
        
        def __init__(
            self,
            expertise: DomainExpertise,
            expertise_level: ExpertiseLevel = ExpertiseLevel.EXPERT,
            temperature: float = 0.3
        ):
            """
            Initialize domain expert agent.
            
            Args:
                expertise: Domain expertise definition
                expertise_level: Level of expertise
                temperature: LLM temperature (lower for more consistent expert advice)
            """
            self.expertise = expertise
            self.expertise_level = expertise_level
            self.llm = ChatOpenAI(temperature=temperature, model="gpt-3.5-turbo")
            self.knowledge_base: List[DomainKnowledge] = []
            self.consultation_history: List[Dict[str, Any]] = []
        
        def _build_expert_context(self) -> str:
            """Build expert context for prompts."""
            context_parts = [
                f"You are a {self.expertise_level.value}-level expert in {self.expertise.domain_name}.",
                f"Domain: {self.expertise.description}",
            ]
            
            if self.expertise.expertise_areas:
                areas = ", ".join(self.expertise.expertise_areas)
                context_parts.append(f"Areas of expertise: {areas}")
            
            if self.expertise.methodologies:
                methods = ", ".join(self.expertise.methodologies)
                context_parts.append(f"Standard methodologies: {methods}")
            
            if self.expertise.standards:
                standards = ", ".join(self.expertise.standards)
                context_parts.append(f"Relevant standards: {standards}")
            
            if self.expertise.best_practices:
                practices = "\n".join([f"  - {p}" for p in self.expertise.best_practices])
                context_parts.append(f"Best practices:\n{practices}")
            
            if self.expertise.key_concepts:
                concepts = "\n".join([f"  - {k}: {v}" for k, v in self.expertise.key_concepts.items()])
                context_parts.append(f"Key concepts:\n{concepts}")
            
            return "\n".join(context_parts)
        
        def add_knowledge(self, knowledge: DomainKnowledge):
            """Add domain knowledge to expert's knowledge base."""
            self.knowledge_base.append(knowledge)
        
        def consult(
            self,
            question: str,
            context: Optional[str] = None,
            require_reasoning: bool = True
        ) -> ExpertResponse:
            """
            Provide expert consultation.
            
            Args:
                question: Question or problem
                context: Additional context
                require_reasoning: Include reasoning explanation
                
            Returns:
                Expert response
            """
            expert_context = self._build_expert_context()
            
            # Build prompt
            prompt_template = (
                "{expert_context}\n\n"
                "Provide expert guidance on the following:\n\n"
                "Question: {question}\n\n"
            )
            
            if context:
                prompt_template += "Additional Context: {context}\n\n"
            
            prompt_template += (
                "Provide a comprehensive expert response including:\n"
                "1. Direct answer\n"
                "2. Expert reasoning and analysis\n"
                "3. Relevant considerations and caveats\n"
                "4. Best practices to follow\n"
                "5. Potential alternatives or approaches\n\n"
                "Use appropriate domain terminology and cite relevant standards when applicable."
            )
            
            prompt = ChatPromptTemplate.from_template(prompt_template)
            chain = prompt | self.llm | StrOutputParser()
            
            input_data = {
                "expert_context": expert_context,
                "question": question
            }
            
            if context:
                input_data["context"] = context
            
            response_text = chain.invoke(input_data)
            
            # Assess confidence based on question clarity and domain coverage
            confidence = self._assess_confidence(question)
            
            # Parse response components
            answer, reasoning, caveats = self._parse_response(response_text)
            
            # Store consultation
            self.consultation_history.append({
                "question": question,
                "answer": answer,
                "timestamp": datetime.now(),
                "confidence": confidence.value
            })
            
            return ExpertResponse(
                answer=answer,
                confidence=confidence,
                reasoning=reasoning,
                caveats=caveats
            )
        
        def _assess_confidence(self, question: str) -> ConfidenceLevel:
            """
            Assess confidence level in response.
            
            Args:
                question: The question asked
                
            Returns:
                Confidence level
            """
            # Check if question relates to core expertise
            question_lower = question.lower()
            
            # Count matches with expertise areas
            expertise_matches = sum(
                1 for area in self.expertise.expertise_areas
                if area.lower() in question_lower
            )
            
            # Terminology matches
            terminology_matches = sum(
                1 for term in self.expertise.terminology.keys()
                if term.lower() in question_lower
            )
            
            total_matches = expertise_matches + terminology_matches
            
            if total_matches >= 3:
                return ConfidenceLevel.VERY_HIGH
            elif total_matches >= 2:
                return ConfidenceLevel.HIGH
            elif total_matches >= 1:
                return ConfidenceLevel.MEDIUM
            else:
                return ConfidenceLevel.LOW
        
        def _parse_response(self, response_text: str) -> Tuple[str, str, List[str]]:
            """Parse response into components."""
            # Simple parsing - in production, use more sophisticated extraction
            lines = response_text.split('\n')
            
            answer_lines = []
            reasoning_lines = []
            caveat_lines = []
            
            current_section = "answer"
            
            for line in lines:
                line_lower = line.lower()
                
                if "reasoning" in line_lower or "analysis" in line_lower:
                    current_section = "reasoning"
                elif "caveat" in line_lower or "consideration" in line_lower or "warning" in line_lower:
                    current_section = "caveats"
                elif line.strip():
                    if current_section == "answer":
                        answer_lines.append(line)
                    elif current_section == "reasoning":
                        reasoning_lines.append(line)
                    elif current_section == "caveats":
                        caveat_lines.append(line)
            
            answer = "\n".join(answer_lines) if answer_lines else response_text
            reasoning = "\n".join(reasoning_lines)
            caveats = [line.strip('- ').strip() for line in caveat_lines if line.strip()]
            
            return answer, reasoning, caveats
        
        def explain_concept(self, concept: str, audience_level: str = "intermediate") -> str:
            """
            Explain a domain concept.
            
            Args:
                concept: Concept to explain
                audience_level: Target audience (novice/intermediate/advanced)
                
            Returns:
                Explanation
            """
            expert_context = self._build_expert_context()
            
            # Check if concept is in terminology
            concept_definition = self.expertise.terminology.get(concept, "")
            
            prompt = ChatPromptTemplate.from_template(
                "{expert_context}\n\n"
                "Explain the concept of '{concept}' for a {audience_level} audience.\n"
                "{definition_context}\n"
                "Provide:\n"
                "1. Clear definition\n"
                "2. Key characteristics\n"
                "3. Practical examples\n"
                "4. Common misconceptions\n"
                "5. Related concepts\n\n"
                "Use appropriate technical depth for the audience level."
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            definition_context = f"Domain definition: {concept_definition}" if concept_definition else ""
            
            explanation = chain.invoke({
                "expert_context": expert_context,
                "concept": concept,
                "audience_level": audience_level,
                "definition_context": definition_context
            })
            
            return explanation
        
        def identify_issues(self, scenario: str) -> List[str]:
            """
            Identify potential issues in a scenario.
            
            Args:
                scenario: Description of situation
                
            Returns:
                List of identified issues
            """
            expert_context = self._build_expert_context()
            
            # Include common issues from domain
            common_issues = "\n".join([f"- {issue}" for issue in self.expertise.common_issues])
            
            prompt = ChatPromptTemplate.from_template(
                "{expert_context}\n\n"
                "Common issues in this domain:\n"
                "{common_issues}\n\n"
                "Scenario:\n"
                "{scenario}\n\n"
                "As an expert, identify potential issues, problems, or concerns in this scenario.\n"
                "List each issue on a separate line starting with '- '."
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            response = chain.invoke({
                "expert_context": expert_context,
                "common_issues": common_issues,
                "scenario": scenario
            })
            
            # Parse issues
            issues = [
                line.strip('- ').strip()
                for line in response.split('\n')
                if line.strip().startswith('-')
            ]
            
            return issues
        
        def recommend_approach(self, problem: str) -> Dict[str, Any]:
            """
            Recommend approach for solving a problem.
            
            Args:
                problem: Problem description
                
            Returns:
                Recommended approach with rationale
            """
            expert_context = self._build_expert_context()
            
            methodologies = ", ".join(self.expertise.methodologies)
            practices = "\n".join([f"- {p}" for p in self.expertise.best_practices])
            
            prompt = ChatPromptTemplate.from_template(
                "{expert_context}\n\n"
                "Available methodologies: {methodologies}\n\n"
                "Best practices:\n"
                "{practices}\n\n"
                "Problem:\n"
                "{problem}\n\n"
                "Recommend the best approach to solve this problem. Include:\n"
                "APPROACH: [recommended approach]\n"
                "METHODOLOGY: [which methodology to use]\n"
                "STEPS: [key steps]\n"
                "RATIONALE: [why this approach]\n"
                "ALTERNATIVES: [other options]"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            response = chain.invoke({
                "expert_context": expert_context,
                "methodologies": methodologies,
                "practices": practices,
                "problem": problem
            })
            
            # Parse recommendation
            return {
                "raw_response": response,
                "problem": problem,
                "timestamp": datetime.now()
            }
        
        def get_expertise_summary(self) -> Dict[str, Any]:
            """Get summary of expert capabilities."""
            return {
                "domain": self.expertise.domain_name,
                "description": self.expertise.description,
                "expertise_level": self.expertise_level.value,
                "areas_of_expertise": self.expertise.expertise_areas,
                "methodologies": self.expertise.methodologies,
                "standards": self.expertise.standards,
                "total_consultations": len(self.consultation_history),
                "knowledge_base_size": len(self.knowledge_base)
            }
    
    
    def demonstrate_domain_expert():
        """Demonstrate domain expert agent pattern."""
        
        print("=" * 80)
        print("DOMAIN EXPERT AGENT PATTERN DEMONSTRATION")
        print("=" * 80)
        
        # Example 1: Software Architecture Expert
        print("\n" + "=" * 80)
        print("Example 1: Software Architecture Expert")
        print("=" * 80)
        
        software_expertise = DomainExpertise(
            domain_name="Software Architecture",
            description="Design and structure of software systems",
            expertise_areas=[
                "Microservices",
                "System Design",
                "Scalability",
                "Design Patterns",
                "API Design"
            ],
            methodologies=[
                "Domain-Driven Design",
                "Clean Architecture",
                "Event-Driven Architecture",
                "Hexagonal Architecture"
            ],
            key_concepts={
                "Separation of Concerns": "Dividing system into distinct features with minimal overlap",
                "SOLID Principles": "Five design principles for maintainable software",
                "Scalability": "Ability to handle growth in workload"
            },
            terminology={
                "Microservice": "Small, independent service focused on single business capability",
                "API Gateway": "Single entry point for all client requests",
                "Circuit Breaker": "Pattern preventing cascading failures"
            },
            standards=[
                "REST API Design",
                "OpenAPI Specification",
                "12-Factor App"
            ],
            common_issues=[
                "Tight coupling between components",
                "Lack of scalability planning",
                "Poor API design",
                "Missing error handling",
                "Inadequate monitoring"
            ],
            best_practices=[
                "Design for failure",
                "Implement proper logging and monitoring",
                "Use asynchronous communication where appropriate",
                "Maintain clear API contracts",
                "Document architectural decisions"
            ]
        )
        
        architect = DomainExpertAgent(
            expertise=software_expertise,
            expertise_level=ExpertiseLevel.EXPERT
        )
        
        print(f"\nExpert Domain: {software_expertise.domain_name}")
        print(f"Expertise Level: {architect.expertise_level.value}")
        print(f"Areas: {', '.join(software_expertise.expertise_areas[:3])}...")
        
        # Example 2: Expert consultation
        print("\n" + "=" * 80)
        print("Example 2: Expert Consultation")
        print("=" * 80)
        
        question = "I'm building an e-commerce platform. Should I use microservices or a monolith?"
        
        print(f"\nQuestion: {question}")
        print("\nExpert Response:")
        print("-" * 60)
        
        response = architect.consult(question)
        print(response.answer)
        print(f"\nConfidence: {response.confidence.value}")
        
        if response.caveats:
            print(f"\nCaveats:")
            for caveat in response.caveats:
                print(f"  - {caveat}")
        
        # Example 3: Concept explanation
        print("\n" + "=" * 80)
        print("Example 3: Explaining Domain Concepts")
        print("=" * 80)
        
        concept = "Microservice"
        audience = "intermediate"
        
        print(f"\nExplaining '{concept}' for {audience} audience:")
        print("-" * 60)
        
        explanation = architect.explain_concept(concept, audience_level=audience)
        print(explanation)
        
        # Example 4: Issue identification
        print("\n" + "=" * 80)
        print("Example 4: Identifying Issues in Scenario")
        print("=" * 80)
        
        scenario = """
        We have a system where the web frontend directly calls the database.
        All services share the same database. We deploy everything together as one unit.
        When traffic increases, the entire system slows down.
        """
        
        print("\nScenario:")
        print(scenario)
        print("\nIdentified Issues:")
        
        issues = architect.identify_issues(scenario)
        for i, issue in enumerate(issues, 1):
            print(f"{i}. {issue}")
        
        # Example 5: Approach recommendation
        print("\n" + "=" * 80)
        print("Example 5: Recommending Approach")
        print("=" * 80)
        
        problem = "Need to scale our notification system that currently sends 10k emails/day but will need to handle 1M/day"
        
        print(f"\nProblem: {problem}")
        print("\nRecommended Approach:")
        print("-" * 60)
        
        recommendation = architect.recommend_approach(problem)
        print(recommendation["raw_response"])
        
        # Example 6: Medical Domain Expert
        print("\n" + "=" * 80)
        print("Example 6: Medical Domain Expert")
        print("=" * 80)
        
        medical_expertise = DomainExpertise(
            domain_name="General Medicine",
            description="Medical diagnosis and treatment",
            expertise_areas=[
                "Symptom Analysis",
                "Differential Diagnosis",
                "Treatment Planning",
                "Patient Care"
            ],
            methodologies=[
                "Evidence-Based Medicine",
                "Clinical Decision Making",
                "Patient-Centered Care"
            ],
            terminology={
                "Differential Diagnosis": "Process of distinguishing between similar conditions",
                "Prognosis": "Predicted course of a disease",
                "Contraindication": "Condition that makes treatment inadvisable"
            },
            standards=[
                "HIPAA Compliance",
                "Clinical Practice Guidelines",
                "Medical Ethics"
            ],
            best_practices=[
                "Always consider patient history",
                "Rule out serious conditions first",
                "Consider drug interactions",
                "Obtain informed consent",
                "Document thoroughly"
            ]
        )
        
        doctor = DomainExpertAgent(
            expertise=medical_expertise,
            expertise_level=ExpertiseLevel.EXPERT,
            temperature=0.2  # Very low for medical advice
        )
        
        print(f"\nExpert Domain: {medical_expertise.domain_name}")
        print(f"Standards: {', '.join(medical_expertise.standards)}")
        
        # Medical consultation
        medical_question = "What should I consider when a patient presents with chest pain?"
        
        print(f"\nMedical Question: {medical_question}")
        print("\nDISCLAIMER: This is a demonstration. Not real medical advice.")
        print("-" * 60)
        
        medical_response = doctor.consult(medical_question)
        print(medical_response.answer[:500] + "...")  # Truncate for demo
        print(f"\nConfidence: {medical_response.confidence.value}")
        
        # Example 7: Financial Expert
        print("\n" + "=" * 80)
        print("Example 7: Financial Planning Expert")
        print("=" * 80)
        
        financial_expertise = DomainExpertise(
            domain_name="Financial Planning",
            description="Personal and business financial planning",
            expertise_areas=[
                "Investment Strategy",
                "Retirement Planning",
                "Tax Planning",
                "Risk Management"
            ],
            methodologies=[
                "Modern Portfolio Theory",
                "Asset Allocation",
                "Risk Assessment"
            ],
            standards=[
                "SEC Regulations",
                "Fiduciary Duty",
                "CFP Standards"
            ],
            best_practices=[
                "Diversify investments",
                "Consider tax implications",
                "Match risk to time horizon",
                "Rebalance regularly",
                "Have emergency fund"
            ]
        )
        
        financial_advisor = DomainExpertAgent(
            expertise=financial_expertise,
            expertise_level=ExpertiseLevel.EXPERT
        )
        
        financial_question = "I'm 30 years old and want to start investing for retirement. Where should I start?"
        
        print(f"\nQuestion: {financial_question}")
        print("\nExpert Guidance:")
        print("-" * 60)
        
        financial_response = financial_advisor.consult(financial_question)
        print(financial_response.answer)
        
        # Example 8: Expertise summary
        print("\n" + "=" * 80)
        print("Example 8: Expert Capabilities Summary")
        print("=" * 80)
        
        summary = architect.get_expertise_summary()
        
        print("\nEXPERT PROFILE:")
        print("=" * 60)
        print(f"Domain: {summary['domain']}")
        print(f"Expertise Level: {summary['expertise_level']}")
        print(f"\nAreas of Expertise:")
        for area in summary['areas_of_expertise']:
            print(f"  • {area}")
        print(f"\nMethodologies:")
        for method in summary['methodologies']:
            print(f"  • {method}")
        print(f"\nTotal Consultations: {summary['total_consultations']}")
        
        # Summary
        print("\n" + "=" * 80)
        print("SUMMARY: Domain Expert Agent Pattern")
        print("=" * 80)
        
        summary_text = """
        The Domain Expert Agent pattern demonstrated:
        
        1. EXPERTISE DEFINITION (Example 1):
           - Comprehensive domain specification
           - Areas of expertise
           - Standard methodologies
           - Key concepts and terminology
           - Relevant standards and regulations
           - Common issues and challenges
           - Best practices
        
        2. EXPERT CONSULTATION (Example 2):
           - Professional guidance
           - Domain-appropriate reasoning
           - Confidence assessment
           - Caveat identification
           - Best practice application
        
        3. CONCEPT EXPLANATION (Example 3):
           - Audience-appropriate depth
           - Domain terminology
           - Practical examples
           - Clear definitions
           - Related concepts
        
        4. ISSUE IDENTIFICATION (Example 4):
           - Expert problem recognition
           - Domain-specific concerns
           - Pattern matching
           - Risk assessment
           - Comprehensive analysis
        
        5. APPROACH RECOMMENDATION (Example 5):
           - Methodology selection
           - Step-by-step guidance
           - Rationale explanation
           - Alternative considerations
           - Best practice integration
        
        6. DOMAIN SPECIALIZATION (Examples 6-7):
           - Medical expertise
           - Financial planning
           - Different domain requirements
           - Standards compliance
           - Professional ethics
        
        7. MULTI-DOMAIN CAPABILITY (Examples 1, 6, 7):
           - Software architecture
           - Medical diagnosis
           - Financial planning
           - Domain-specific reasoning
           - Appropriate terminology
        
        8. TRANSPARENCY (Example 8):
           - Expertise summary
           - Capability disclosure
           - Consultation tracking
           - Knowledge base size
           - Performance metrics
        
        KEY BENEFITS:
        ✓ Expert-level guidance
        ✓ Domain-appropriate reasoning
        ✓ Specialized knowledge application
        ✓ Professional terminology
        ✓ Best practice adherence
        ✓ Quality assurance
        ✓ Credible advice
        ✓ Comprehensive coverage
        
        USE CASES:
        • Medical diagnosis assistance
        • Legal research and advisory
        • Financial analysis and planning
        • Engineering consultation
        • Scientific research support
        • Tax preparation
        • Architectural design
        • Software architecture advisory
        
        EXPERT BEHAVIORS:
        → Ask clarifying questions
        → Identify missing information
        → Consider edge cases
        → Reference standards
        → Explain reasoning
        → Acknowledge uncertainty
        → Provide multiple perspectives
        → Use appropriate terminology
        
        DOMAIN CHARACTERISTICS:
        • Depth: Comprehensive specialized coverage
        • Terminology: Field-specific vocabulary
        • Methodology: Standard approaches
        • Context: Domain landscape understanding
        • Precedents: Historical cases
        • Standards: Industry regulations
        • Boundaries: Expertise limits
        
        BEST PRACTICES:
        1. Regularly update domain knowledge
        2. Version control expert systems
        3. Track predictions vs. outcomes
        4. Include human expert review
        5. Add appropriate disclaimers
        6. Maintain audit trails
        7. Ensure regulatory compliance
        8. Support expert override
        
        TRADE-OFFS:
        • Depth vs. breadth
        • Accuracy vs. accessibility
        • Confidence vs. caution
        • Automation vs. human oversight
        
        PRODUCTION CONSIDERATIONS:
        → Regular knowledge base updates
        → Version control of expertise
        → Track expert vs. actual outcomes
        → Human expert review loops
        → Appropriate disclaimers
        → Complete audit trails
        → Regulatory compliance checks
        → Expert override mechanisms
        → Liability management
        → Certification where applicable
        
        This pattern enables agents to provide professional-grade expertise in
        specialized domains, delivering value that requires deep knowledge and
        experience while maintaining appropriate boundaries and transparency.
        """
        
        print(summary_text)
    
    
    if __name__ == "__main__":
        demonstrate_domain_expert()
    
        

    Agentic Design Pattern: Domain Expert

    Pattern 133: Domain Expert – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Domain Expert pattern implementation.


    Pattern Description

    Pattern 133: Domain Expert Agent

    Description: The Domain Expert Agent pattern creates specialized agents with deep expertise in specific domains or fields. Unlike general-purpose agents, domain experts possess comprehensive knowledge, terminology, methodologies, and best practices specific to their area of specialization. They can provide expert-level advice, perform domain-specific reasoning, and apply specialized knowledge effectively.

    Domain expertise goes beyond simple knowledge retrieval - it includes understanding
    domain-specific workflows, recognizing patterns, applying heuristics, knowing
    what questions to ask, and understanding the nuances and edge cases within the
    domain. Expert agents can explain complex concepts using domain terminology,
    evaluate solutions using domain-specific criteria, and provide guidance that
    reflects years of accumulated expertise.
    
    This pattern is essential for applications requiring specialized knowledge such
    as medical diagnosis assistants, legal advisors, financial analysts, scientific
    research assistants, engineering consultants, and other professional AI systems.
    

    Key Components: 1. Domain Knowledge Base: Comprehensive domain-specific information 2. Terminology Handler: Domain-specific vocabulary and jargon 3. Best Practices Repository: Field-standard methodologies 4. Case History: Examples and precedents from the domain 5. Reasoning Engine: Domain-specific logic and heuristics 6. Validation System: Domain-appropriate quality checks 7. Reference System: Citations and sources

    Domain Characteristics: 1. Depth: Comprehensive coverage of specialized area 2. Terminology: Field-specific vocabulary 3. Methodology: Domain-standard approaches 4. Context: Understanding of domain landscape 5. Precedents: Historical cases and examples 6. Standards: Industry regulations and best practices 7. Boundaries: Knowing limits of expertise

    Expert Behaviors: 1. Ask clarifying questions 2. Identify missing information 3. Consider edge cases 4. Reference standards and regulations 5. Explain reasoning process 6. Acknowledge uncertainty 7. Provide multiple perspectives 8. Use appropriate terminology

    Use Cases: – Medical diagnosis assistants – Legal research and advisory – Financial analysis and planning – Engineering design consultation – Scientific research assistance – Tax preparation and planning – Architectural design – Software architecture advisory

    Advantages: – Expert-level guidance – Domain-appropriate reasoning – Specialized knowledge application – Professional terminology usage – Best practice adherence – Quality assurance – Credible advice

    Challenges: – Knowledge maintenance and updates – Handling edge cases – Avoiding overconfidence – Managing liability concerns – Balancing depth vs. accessibility – Keeping current with field changes – Regulatory compliance

    LangChain Implementation: This implementation uses LangChain for: – Domain knowledge integration – Expert reasoning chains – Specialized RAG with domain documents – Domain-specific validation

    Production Considerations: – Regularly update domain knowledge – Version control expert systems – Track expert vs. actual outcomes – Implement human expert review – Include disclaimers appropriately – Maintain audit trails – Ensure regulatory compliance – Support expert override mechanisms


    File Statistics

    • Total Lines: 946
    • Classes: 6
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 133: Domain Expert Agent
    
    Description:
        The Domain Expert Agent pattern creates specialized agents with deep expertise
        in specific domains or fields. Unlike general-purpose agents, domain experts
        possess comprehensive knowledge, terminology, methodologies, and best practices
        specific to their area of specialization. They can provide expert-level advice,
        perform domain-specific reasoning, and apply specialized knowledge effectively.
    
        Domain expertise goes beyond simple knowledge retrieval - it includes understanding
        domain-specific workflows, recognizing patterns, applying heuristics, knowing
        what questions to ask, and understanding the nuances and edge cases within the
        domain. Expert agents can explain complex concepts using domain terminology,
        evaluate solutions using domain-specific criteria, and provide guidance that
        reflects years of accumulated expertise.
    
        This pattern is essential for applications requiring specialized knowledge such
        as medical diagnosis assistants, legal advisors, financial analysts, scientific
        research assistants, engineering consultants, and other professional AI systems.
    
    Key Components:
        1. Domain Knowledge Base: Comprehensive domain-specific information
        2. Terminology Handler: Domain-specific vocabulary and jargon
        3. Best Practices Repository: Field-standard methodologies
        4. Case History: Examples and precedents from the domain
        5. Reasoning Engine: Domain-specific logic and heuristics
        6. Validation System: Domain-appropriate quality checks
        7. Reference System: Citations and sources
    
    Domain Characteristics:
        1. Depth: Comprehensive coverage of specialized area
        2. Terminology: Field-specific vocabulary
        3. Methodology: Domain-standard approaches
        4. Context: Understanding of domain landscape
        5. Precedents: Historical cases and examples
        6. Standards: Industry regulations and best practices
        7. Boundaries: Knowing limits of expertise
    
    Expert Behaviors:
        1. Ask clarifying questions
        2. Identify missing information
        3. Consider edge cases
        4. Reference standards and regulations
        5. Explain reasoning process
        6. Acknowledge uncertainty
        7. Provide multiple perspectives
        8. Use appropriate terminology
    
    Use Cases:
        - Medical diagnosis assistants
        - Legal research and advisory
        - Financial analysis and planning
        - Engineering design consultation
        - Scientific research assistance
        - Tax preparation and planning
        - Architectural design
        - Software architecture advisory
    
    Advantages:
        - Expert-level guidance
        - Domain-appropriate reasoning
        - Specialized knowledge application
        - Professional terminology usage
        - Best practice adherence
        - Quality assurance
        - Credible advice
    
    Challenges:
        - Knowledge maintenance and updates
        - Handling edge cases
        - Avoiding overconfidence
        - Managing liability concerns
        - Balancing depth vs. accessibility
        - Keeping current with field changes
        - Regulatory compliance
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Domain knowledge integration
        - Expert reasoning chains
        - Specialized RAG with domain documents
        - Domain-specific validation
    
    Production Considerations:
        - Regularly update domain knowledge
        - Version control expert systems
        - Track expert vs. actual outcomes
        - Implement human expert review
        - Include disclaimers appropriately
        - Maintain audit trails
        - Ensure regulatory compliance
        - Support expert override mechanisms
    """
    

    Purpose: This module implements the Domain Expert pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    import typing.Tuple
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Tuple: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: ExpertiseLevel

    Lines 110-116

    Inherits from: Enum

    Purpose:

    Level of expertise.
    

    Class: ConfidenceLevel

    Lines 119-124

    Inherits from: Enum

    Purpose:

    Confidence in response.
    

    Class: DomainKnowledge

    Lines 128-145

    Purpose:

    Domain-specific knowledge item.
    
    Attributes:
        topic: Knowledge area
        content: Information content
        source: Where knowledge came from
        reliability: How reliable (0-1)
        last_updated: When last verified
        tags: Categorization tags
    

    Class: ExpertResponse

    Lines 149-168

    Purpose:

    Expert agent response.
    
    Attributes:
        answer: Main response
        confidence: Confidence level
        reasoning: Explanation of reasoning
        references: Supporting sources
        caveats: Important limitations or warnings
        follow_up_questions: Suggested clarifications
        alternatives: Alternative approaches
    

    Class: DomainExpertise

    Lines 172-195

    Purpose:

    Definition of domain expertise.
    
    Attributes:
        domain_name: Name of domain
        description: Domain description
        expertise_areas: Specific areas of expertise
        methodologies: Standard approaches
        key_concepts: Important domain concepts
        terminology: Domain-specific vocabulary
        standards: Relevant standards and regulations
        common_issues: Frequently encountered problems
        best_practices: Field best practices
    

    Class: DomainExpertAgent

    Lines 198-541

    Purpose:

    Agent with specialized domain expertise.
    
    This agent provides expert-level guidance in a specific domain,
    using specialized knowledge, terminology, and reasoning.
    

    Methods:

    __init__(self, expertise, expertise_level, temperature)

    Lines 206-224

    Purpose:

    Initialize domain expert agent.
    
    Args:
        expertise: Domain expertise definition
        expertise_level: Level of expertise
        temperature: LLM temperature (lower for more consistent expert advice)
    

    Parameters: – expertise: Expertise – expertise_level: Expertise level – temperature: Sampling temperature (0-1)

    _build_expert_context(self)

    Lines 226-253

    Purpose:

    Build expert context for prompts.
    

    Parameters:

    Returns: str

    add_knowledge(self, knowledge)

    Lines 255-257

    Purpose:

    Add domain knowledge to expert's knowledge base.
    

    Parameters: – knowledge: Knowledge

    consult(self, question, context, require_reasoning)

    Lines 259-330

    Purpose:

    Provide expert consultation.
    
    Args:
        question: Question or problem
        context: Additional context
        require_reasoning: Include reasoning explanation
    
    Returns:
        Expert response
    

    Parameters: – question: Question to answer – context: Context – require_reasoning: Require reasoning

    Returns: ExpertResponse

    _assess_confidence(self, question)

    Lines 332-366

    Purpose:

    Assess confidence level in response.
    
    Args:
        question: The question asked
    
    Returns:
        Confidence level
    

    Parameters: – question: Question to answer

    Returns: ConfidenceLevel

    _parse_response(self, response_text)

    Lines 368-398

    Purpose:

    Parse response into components.
    

    Parameters: – response_text: Response text

    Returns: <ast.Subscript object at 0x000001A06D63D090>

    explain_concept(self, concept, audience_level)

    Lines 400-440

    Purpose:

    Explain a domain concept.
    
    Args:
        concept: Concept to explain
        audience_level: Target audience (novice/intermediate/advanced)
    
    Returns:
        Explanation
    

    Parameters: – concept: Concept – audience_level: Audience level

    Returns: str

    identify_issues(self, scenario)

    Lines 442-482

    Purpose:

    Identify potential issues in a scenario.
    
    Args:
        scenario: Description of situation
    
    Returns:
        List of identified issues
    

    Parameters: – scenario: Scenario

    Returns: <ast.Subscript object at 0x000001A06D77E010>

    recommend_approach(self, problem)

    Lines 484-528

    Purpose:

    Recommend approach for solving a problem.
    
    Args:
        problem: Problem description
    
    Returns:
        Recommended approach with rationale
    

    Parameters: – problem: Problem

    Returns: <ast.Subscript object at 0x000001A06D7504D0>

    get_expertise_summary(self)

    Lines 530-541

    Purpose:

    Get summary of expert capabilities.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D168B90>


    Functions

    demonstrate_domain_expert()

    Lines 544-941

    Purpose:

    Demonstrate domain expert agent pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Domain Expert pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 132
    • Pattern 134

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Domain Expert pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 133_domain_expert.py
    Total Lines: 946
    Pattern Category: AI Agent Design Pattern #133


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Emotion Recognition

    
        """
    Pattern 132: Emotion Recognition & Response
    
    Description:
        The Emotion Recognition & Response pattern enables agents to detect emotional
        states from user input and respond with appropriate empathy, tone, and content.
        Rather than treating all interactions uniformly, the agent recognizes emotions
        like frustration, joy, sadness, or confusion and adapts its behavior to be
        contextually appropriate and emotionally intelligent.
        
        This pattern is critical for creating human-centered AI that can build rapport,
        de-escalate conflicts, celebrate successes, and provide appropriate support
        based on user emotional state. It combines emotion detection (analyzing text
        for emotional cues), sentiment analysis, empathetic response generation, and
        emotional context tracking over conversations.
        
        The pattern addresses challenges like subtle emotion detection, cultural
        differences in expression, appropriate emotional responses, avoiding
        manipulation, and maintaining authenticity while being supportive.
    
    Key Components:
        1. Emotion Detection: Identify emotions from text
        2. Sentiment Analysis: Classify overall tone (positive/negative/neutral)
        3. Emotional Intensity: Measure emotion strength
        4. Context Tracking: Track emotional arc over conversation
        5. Empathetic Response: Generate appropriate reactions
        6. Tone Adaptation: Adjust agent tone based on user emotion
        7. Intervention Logic: Special handling for extreme emotions
    
    Emotion Categories:
        1. Primary Emotions: Joy, sadness, anger, fear, surprise, disgust
        2. Complex Emotions: Frustration, excitement, confusion, satisfaction
        3. Social Emotions: Gratitude, embarrassment, pride, shame
        4. Cognitive States: Confidence, uncertainty, curiosity, boredom
    
    Detection Signals:
        1. Explicit Expressions: "I'm frustrated", "This is great!"
        2. Exclamation Marks: Multiple !!! or ???
        3. Capitalization: ALL CAPS for emphasis
        4. Word Choice: Emotional vocabulary
        5. Sentence Structure: Short angry bursts vs. rambling confusion
        6. Emoticons/Emoji: 😊 😠 😢 🤔
        7. Negation: "This isn't working", "No luck"
    
    Response Strategies:
        1. Validation: Acknowledge the emotion
        2. Empathy: Show understanding
        3. Support: Offer help or encouragement
        4. De-escalation: Calm strong negative emotions
        5. Celebration: Share in positive emotions
        6. Clarification: Address confusion
        7. Patience: Adjust pace for overwhelm
    
    Use Cases:
        - Customer support (handling complaints)
        - Mental health chatbots
        - Educational tutors (frustration detection)
        - Healthcare assistants (patient anxiety)
        - HR assistants (employee concerns)
        - Social companions
        - Crisis intervention
    
    Advantages:
        - Improved user satisfaction
        - Better conflict resolution
        - Stronger emotional connection
        - Appropriate tone matching
        - Early problem detection
        - Personalized support
        - Enhanced trust
    
    Challenges:
        - Ambiguous emotional signals
        - Cultural differences in expression
        - Sarcasm and irony detection
        - Over-interpretation risk
        - Privacy and sensitivity
        - Avoiding emotional manipulation
        - Maintaining authenticity
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Emotion detection from text
        - Sentiment classification
        - Empathetic response generation
        - Context-aware emotional tracking
        
    Production Considerations:
        - Use multiple emotion detection methods
        - Track emotional patterns over time
        - Implement crisis detection triggers
        - Provide human escalation paths
        - Respect cultural differences
        - Avoid over-familiarity
        - Log emotion data securely
        - Enable emotion detection toggles
    """
    
    import os
    import re
    from typing import List, Dict, Any, Optional, Tuple
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class Emotion(Enum):
        """Primary emotion categories."""
        JOY = "joy"
        SADNESS = "sadness"
        ANGER = "anger"
        FEAR = "fear"
        SURPRISE = "surprise"
        DISGUST = "disgust"
        FRUSTRATION = "frustration"
        EXCITEMENT = "excitement"
        CONFUSION = "confusion"
        SATISFACTION = "satisfaction"
        GRATITUDE = "gratitude"
        ANXIETY = "anxiety"
        NEUTRAL = "neutral"
    
    
    class Sentiment(Enum):
        """Overall sentiment classification."""
        POSITIVE = "positive"
        NEGATIVE = "negative"
        NEUTRAL = "neutral"
        MIXED = "mixed"
    
    
    class ResponseStrategy(Enum):
        """Strategy for responding to emotions."""
        VALIDATE = "validate"
        EMPATHIZE = "empathize"
        SUPPORT = "support"
        DE_ESCALATE = "de_escalate"
        CELEBRATE = "celebrate"
        CLARIFY = "clarify"
        ENCOURAGE = "encourage"
    
    
    @dataclass
    class EmotionalState:
        """
        Detected emotional state from user input.
        
        Attributes:
            primary_emotion: Main emotion detected
            secondary_emotions: Other emotions present
            sentiment: Overall sentiment
            intensity: Emotion strength (0-1)
            confidence: Detection confidence (0-1)
            signals: Textual cues that indicated emotion
            timestamp: When detected
        """
        primary_emotion: Emotion
        secondary_emotions: List[Emotion] = field(default_factory=list)
        sentiment: Sentiment = Sentiment.NEUTRAL
        intensity: float = 0.5
        confidence: float = 0.5
        signals: List[str] = field(default_factory=list)
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class EmpatheticResponse:
        """
        Response tailored to emotional state.
        
        Attributes:
            response_text: Generated response
            strategy: Strategy used
            acknowledged_emotion: Emotion that was addressed
            tone: Response tone
            follow_up_actions: Suggested next steps
        """
        response_text: str
        strategy: ResponseStrategy
        acknowledged_emotion: Emotion
        tone: str
        follow_up_actions: List[str] = field(default_factory=list)
    
    
    class EmotionalAgent:
        """
        Agent with emotion recognition and empathetic response capabilities.
        
        This agent detects user emotions and responds with appropriate
        empathy, tone, and support.
        """
        
        def __init__(self, temperature: float = 0.7):
            """
            Initialize emotional agent.
            
            Args:
                temperature: LLM temperature for response generation
            """
            self.llm = ChatOpenAI(temperature=temperature, model="gpt-3.5-turbo")
            self.emotional_history: List[EmotionalState] = []
            
            # Emotion keywords for rule-based detection
            self.emotion_keywords = {
                Emotion.JOY: ["happy", "great", "wonderful", "excellent", "love", "amazing", "perfect"],
                Emotion.SADNESS: ["sad", "disappointed", "unhappy", "down", "depressed", "terrible"],
                Emotion.ANGER: ["angry", "furious", "mad", "annoyed", "irritated", "outraged"],
                Emotion.FRUSTRATION: ["frustrated", "stuck", "can't", "won't work", "difficult", "struggle"],
                Emotion.CONFUSION: ["confused", "don't understand", "unclear", "lost", "puzzled"],
                Emotion.GRATITUDE: ["thank", "thanks", "appreciate", "grateful", "helpful"],
                Emotion.ANXIETY: ["worried", "anxious", "nervous", "scared", "concerned"],
                Emotion.EXCITEMENT: ["excited", "can't wait", "awesome", "fantastic", "thrilled"],
            }
        
        def detect_emotion_simple(self, text: str) -> EmotionalState:
            """
            Simple rule-based emotion detection.
            
            Args:
                text: User input text
                
            Returns:
                Detected emotional state
            """
            text_lower = text.lower()
            detected_emotions = []
            signals = []
            
            # Check keywords
            for emotion, keywords in self.emotion_keywords.items():
                for keyword in keywords:
                    if keyword in text_lower:
                        detected_emotions.append(emotion)
                        signals.append(f"Keyword: '{keyword}'")
            
            # Check for caps (anger/excitement)
            if text.isupper() and len(text) > 10:
                detected_emotions.append(Emotion.ANGER)
                signals.append("ALL CAPS")
            
            # Check for exclamation marks
            exclamation_count = text.count('!')
            if exclamation_count >= 2:
                detected_emotions.append(Emotion.EXCITEMENT)
                signals.append(f"Multiple exclamations ({exclamation_count})")
            
            # Check for question marks (confusion)
            question_count = text.count('?')
            if question_count >= 2:
                detected_emotions.append(Emotion.CONFUSION)
                signals.append(f"Multiple questions ({question_count})")
            
            # Determine primary emotion
            if detected_emotions:
                primary = detected_emotions[0]
                secondary = detected_emotions[1:] if len(detected_emotions) > 1 else []
            else:
                primary = Emotion.NEUTRAL
                secondary = []
            
            # Determine sentiment
            positive_emotions = {Emotion.JOY, Emotion.GRATITUDE, Emotion.EXCITEMENT, Emotion.SATISFACTION}
            negative_emotions = {Emotion.SADNESS, Emotion.ANGER, Emotion.FRUSTRATION, Emotion.ANXIETY, Emotion.FEAR}
            
            if primary in positive_emotions:
                sentiment = Sentiment.POSITIVE
            elif primary in negative_emotions:
                sentiment = Sentiment.NEGATIVE
            else:
                sentiment = Sentiment.NEUTRAL
            
            # Estimate intensity
            intensity = 0.5
            if exclamation_count > 0 or text.isupper():
                intensity = 0.8
            elif primary != Emotion.NEUTRAL:
                intensity = 0.6
            
            return EmotionalState(
                primary_emotion=primary,
                secondary_emotions=secondary,
                sentiment=sentiment,
                intensity=intensity,
                confidence=0.7 if signals else 0.3,
                signals=signals
            )
        
        def detect_emotion_llm(self, text: str) -> EmotionalState:
            """
            LLM-based emotion detection.
            
            Args:
                text: User input text
                
            Returns:
                Detected emotional state
            """
            prompt = ChatPromptTemplate.from_template(
                "Analyze the emotional content of this message:\n\n"
                "\"{text}\"\n\n"
                "Provide:\n"
                "PRIMARY_EMOTION: [joy/sadness/anger/fear/frustration/confusion/gratitude/excitement/neutral/etc.]\n"
                "SENTIMENT: [positive/negative/neutral/mixed]\n"
                "INTENSITY: [0.0-1.0, where 0 is no emotion and 1 is extreme]\n"
                "SIGNALS: [what textual cues indicate this emotion]\n"
                "CONFIDENCE: [0.0-1.0, how certain are you]"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            analysis = chain.invoke({"text": text})
            
            # Parse analysis
            lines = analysis.strip().split('\n')
            
            primary_emotion = Emotion.NEUTRAL
            sentiment = Sentiment.NEUTRAL
            intensity = 0.5
            confidence = 0.5
            signals = []
            
            for line in lines:
                if line.startswith("PRIMARY_EMOTION:"):
                    emotion_str = line.split(":")[1].strip().lower()
                    # Map to enum
                    for emotion in Emotion:
                        if emotion.value in emotion_str:
                            primary_emotion = emotion
                            break
                
                elif line.startswith("SENTIMENT:"):
                    sentiment_str = line.split(":")[1].strip().lower()
                    if "positive" in sentiment_str:
                        sentiment = Sentiment.POSITIVE
                    elif "negative" in sentiment_str:
                        sentiment = Sentiment.NEGATIVE
                    elif "mixed" in sentiment_str:
                        sentiment = Sentiment.MIXED
                
                elif line.startswith("INTENSITY:"):
                    try:
                        intensity = float(line.split(":")[1].strip().split()[0])
                    except:
                        pass
                
                elif line.startswith("CONFIDENCE:"):
                    try:
                        confidence = float(line.split(":")[1].strip().split()[0])
                    except:
                        pass
                
                elif line.startswith("SIGNALS:"):
                    signals.append(line.split(":")[1].strip())
            
            return EmotionalState(
                primary_emotion=primary_emotion,
                sentiment=sentiment,
                intensity=intensity,
                confidence=confidence,
                signals=signals
            )
        
        def select_response_strategy(self, emotional_state: EmotionalState) -> ResponseStrategy:
            """
            Select appropriate response strategy.
            
            Args:
                emotional_state: Detected emotional state
                
            Returns:
                Response strategy
            """
            emotion = emotional_state.primary_emotion
            intensity = emotional_state.intensity
            
            # High-intensity negative emotions need de-escalation
            if intensity > 0.7 and emotional_state.sentiment == Sentiment.NEGATIVE:
                return ResponseStrategy.DE_ESCALATE
            
            # Map emotions to strategies
            strategy_map = {
                Emotion.JOY: ResponseStrategy.CELEBRATE,
                Emotion.EXCITEMENT: ResponseStrategy.CELEBRATE,
                Emotion.GRATITUDE: ResponseStrategy.VALIDATE,
                Emotion.SADNESS: ResponseStrategy.EMPATHIZE,
                Emotion.ANGER: ResponseStrategy.DE_ESCALATE,
                Emotion.FRUSTRATION: ResponseStrategy.SUPPORT,
                Emotion.CONFUSION: ResponseStrategy.CLARIFY,
                Emotion.ANXIETY: ResponseStrategy.SUPPORT,
                Emotion.NEUTRAL: ResponseStrategy.VALIDATE
            }
            
            return strategy_map.get(emotion, ResponseStrategy.VALIDATE)
        
        def generate_empathetic_response(
            self,
            user_input: str,
            emotional_state: EmotionalState,
            strategy: ResponseStrategy
        ) -> EmpatheticResponse:
            """
            Generate response tailored to emotional state.
            
            Args:
                user_input: User's message
                emotional_state: Detected emotional state
                strategy: Response strategy to use
                
            Returns:
                Empathetic response
            """
            # Build context about emotion
            emotion_context = (
                f"The user is expressing {emotional_state.primary_emotion.value} "
                f"with {emotional_state.intensity:.1f} intensity. "
                f"Overall sentiment is {emotional_state.sentiment.value}."
            )
            
            # Strategy-specific instructions
            strategy_instructions = {
                ResponseStrategy.VALIDATE: "Acknowledge and validate their feelings.",
                ResponseStrategy.EMPATHIZE: "Show deep empathy and understanding. Be gentle and supportive.",
                ResponseStrategy.SUPPORT: "Offer concrete support and encouragement. Focus on solutions.",
                ResponseStrategy.DE_ESCALATE: "Be calm and soothing. Acknowledge frustration and offer to help resolve issues.",
                ResponseStrategy.CELEBRATE: "Share in their positive emotions! Be enthusiastic and encouraging.",
                ResponseStrategy.CLARIFY: "Help them understand. Be patient and clear. Break things down.",
                ResponseStrategy.ENCOURAGE: "Provide motivation and confidence. Highlight their strengths."
            }
            
            instruction = strategy_instructions.get(strategy, "Respond appropriately.")
            
            prompt = ChatPromptTemplate.from_template(
                "User message: \"{user_input}\"\n\n"
                "Emotional Context: {emotion_context}\n\n"
                "Response Strategy: {strategy}\n"
                "Instruction: {instruction}\n\n"
                "Generate an empathetic, helpful response that appropriately addresses "
                "the user's emotional state. Be genuine and human-like."
            )
            
            chain = prompt | self.llm | StrOutputParser()
            
            response_text = chain.invoke({
                "user_input": user_input,
                "emotion_context": emotion_context,
                "strategy": strategy.value,
                "instruction": instruction
            })
            
            # Determine tone
            tone_map = {
                ResponseStrategy.CELEBRATE: "enthusiastic",
                ResponseStrategy.EMPATHIZE: "gentle",
                ResponseStrategy.DE_ESCALATE: "calm",
                ResponseStrategy.CLARIFY: "patient",
                ResponseStrategy.SUPPORT: "encouraging",
                ResponseStrategy.VALIDATE: "understanding"
            }
            
            return EmpatheticResponse(
                response_text=response_text,
                strategy=strategy,
                acknowledged_emotion=emotional_state.primary_emotion,
                tone=tone_map.get(strategy, "neutral")
            )
        
        def respond(self, user_input: str, use_llm_detection: bool = True) -> str:
            """
            Process input and generate empathetic response.
            
            Args:
                user_input: User's message
                use_llm_detection: Use LLM vs. rule-based detection
                
            Returns:
                Empathetic response text
            """
            # Detect emotion
            if use_llm_detection:
                emotional_state = self.detect_emotion_llm(user_input)
            else:
                emotional_state = self.detect_emotion_simple(user_input)
            
            # Store in history
            self.emotional_history.append(emotional_state)
            
            # Select strategy
            strategy = self.select_response_strategy(emotional_state)
            
            # Generate response
            response = self.generate_empathetic_response(user_input, emotional_state, strategy)
            
            return response.response_text
        
        def get_emotional_trajectory(self) -> List[Dict[str, Any]]:
            """Get emotional arc over conversation."""
            return [
                {
                    "emotion": state.primary_emotion.value,
                    "sentiment": state.sentiment.value,
                    "intensity": state.intensity,
                    "timestamp": state.timestamp.isoformat()
                }
                for state in self.emotional_history
            ]
        
        def get_current_emotional_state(self) -> Optional[EmotionalState]:
            """Get most recent emotional state."""
            return self.emotional_history[-1] if self.emotional_history else None
    
    
    def demonstrate_emotion_recognition():
        """Demonstrate emotion recognition and response pattern."""
        
        print("=" * 80)
        print("EMOTION RECOGNITION & RESPONSE PATTERN DEMONSTRATION")
        print("=" * 80)
        
        # Example 1: Basic emotion detection
        print("\n" + "=" * 80)
        print("Example 1: Basic Emotion Detection")
        print("=" * 80)
        
        agent = EmotionalAgent()
        
        test_messages = [
            "I'm so frustrated! This isn't working at all!",
            "Thank you so much! This is exactly what I needed!",
            "I'm a bit confused about how this works...",
            "This is terrible. I'm very disappointed.",
            "WOW! This is AMAZING!!!"
        ]
        
        print("\nDetecting emotions in various messages:")
        for msg in test_messages:
            emotion_state = agent.detect_emotion_simple(msg)
            print(f"\nMessage: \"{msg}\"")
            print(f"  Primary Emotion: {emotion_state.primary_emotion.value}")
            print(f"  Sentiment: {emotion_state.sentiment.value}")
            print(f"  Intensity: {emotion_state.intensity:.2f}")
            print(f"  Signals: {emotion_state.signals}")
        
        # Example 2: LLM-based detection
        print("\n" + "=" * 80)
        print("Example 2: LLM-Based Emotion Detection")
        print("=" * 80)
        
        complex_message = "I've been trying this for hours and nothing works. I'm starting to think I'm just not smart enough for this."
        
        print(f"\nAnalyzing complex message:")
        print(f'"{complex_message}"')
        
        emotion_state = agent.detect_emotion_llm(complex_message)
        print(f"\nPrimary Emotion: {emotion_state.primary_emotion.value}")
        print(f"Sentiment: {emotion_state.sentiment.value}")
        print(f"Intensity: {emotion_state.intensity:.2f}")
        print(f"Confidence: {emotion_state.confidence:.2f}")
        print(f"Signals: {emotion_state.signals}")
        
        # Example 3: Strategy selection
        print("\n" + "=" * 80)
        print("Example 3: Response Strategy Selection")
        print("=" * 80)
        
        emotions_and_strategies = [
            (Emotion.FRUSTRATION, 0.8, Sentiment.NEGATIVE),
            (Emotion.JOY, 0.9, Sentiment.POSITIVE),
            (Emotion.CONFUSION, 0.6, Sentiment.NEUTRAL),
            (Emotion.ANGER, 0.9, Sentiment.NEGATIVE),
        ]
        
        print("\nStrategy selection for different emotional states:")
        for emotion, intensity, sentiment in emotions_and_strategies:
            state = EmotionalState(
                primary_emotion=emotion,
                sentiment=sentiment,
                intensity=intensity
            )
            strategy = agent.select_response_strategy(state)
            print(f"\n{emotion.value} (intensity={intensity}, {sentiment.value})")
            print(f"  → Strategy: {strategy.value}")
        
        # Example 4: Empathetic responses
        print("\n" + "=" * 80)
        print("Example 4: Empathetic Response Generation")
        print("=" * 80)
        
        agent2 = EmotionalAgent()
        
        scenarios = [
            "I'm so frustrated! I've been stuck on this problem for hours!",
            "This is absolutely perfect! You've made my day!",
            "I don't understand how this feature works. Can you help?"
        ]
        
        print("\nGenerating empathetic responses:")
        for scenario in scenarios:
            print(f"\nUser: {scenario}")
            response = agent2.respond(scenario)
            
            # Get emotional state
            state = agent2.get_current_emotional_state()
            print(f"Detected: {state.primary_emotion.value} ({state.intensity:.2f} intensity)")
            print(f"Agent: {response}")
        
        # Example 5: De-escalation
        print("\n" + "=" * 80)
        print("Example 5: De-escalation of Strong Negative Emotions")
        print("=" * 80)
        
        agent3 = EmotionalAgent()
        
        angry_message = "This is completely unacceptable! I've wasted so much time and nothing works! I want a refund NOW!"
        
        print(f"\nAngry User: {angry_message}")
        
        response = agent3.respond(angry_message)
        state = agent3.get_current_emotional_state()
        
        print(f"\nDetected Emotion: {state.primary_emotion.value}")
        print(f"Intensity: {state.intensity:.2f}")
        print(f"Sentiment: {state.sentiment.value}")
        print(f"\nAgent (De-escalation): {response}")
        
        # Example 6: Celebration
        print("\n" + "=" * 80)
        print("Example 6: Celebrating Positive Emotions")
        print("=" * 80)
        
        agent4 = EmotionalAgent()
        
        excited_message = "I finally got it working!!! This is amazing! Thank you so much!"
        
        print(f"\nExcited User: {excited_message}")
        
        response = agent4.respond(excited_message)
        state = agent4.get_current_emotional_state()
        
        print(f"\nDetected Emotion: {state.primary_emotion.value}")
        print(f"Intensity: {state.intensity:.2f}")
        print(f"\nAgent (Celebration): {response}")
        
        # Example 7: Emotional trajectory
        print("\n" + "=" * 80)
        print("Example 7: Tracking Emotional Trajectory")
        print("=" * 80)
        
        agent5 = EmotionalAgent()
        
        conversation = [
            "I'm trying to set this up but it's not working.",
            "I've tried everything! This is so frustrating!",
            "Oh wait, I think I see the issue now.",
            "Yes! It's working now! Thank you!"
        ]
        
        print("\nConversation with emotional tracking:")
        for msg in conversation:
            print(f"\nUser: {msg}")
            response = agent5.respond(msg)
            state = agent5.get_current_emotional_state()
            print(f"[{state.primary_emotion.value}, intensity={state.intensity:.2f}]")
            print(f"Agent: {response}")
        
        print("\n" + "-" * 60)
        print("\nEMOTIONAL TRAJECTORY:")
        trajectory = agent5.get_emotional_trajectory()
        for i, point in enumerate(trajectory, 1):
            print(f"{i}. {point['emotion']} ({point['sentiment']}) - intensity: {point['intensity']:.2f}")
        
        # Example 8: Mixed emotions
        print("\n" + "=" * 80)
        print("Example 8: Handling Mixed/Complex Emotions")
        print("=" * 80)
        
        agent6 = EmotionalAgent()
        
        mixed_message = "I'm excited about this new feature, but also worried I won't be able to learn it in time."
        
        print(f"\nUser: {mixed_message}")
        
        response = agent6.respond(mixed_message)
        state = agent6.get_current_emotional_state()
        
        print(f"\nDetected Primary: {state.primary_emotion.value}")
        print(f"Secondary: {[e.value for e in state.secondary_emotions]}")
        print(f"Sentiment: {state.sentiment.value}")
        print(f"\nAgent: {response}")
        
        # Summary
        print("\n" + "=" * 80)
        print("SUMMARY: Emotion Recognition & Response Pattern")
        print("=" * 80)
        
        summary = """
        The Emotion Recognition & Response pattern demonstrated:
        
        1. EMOTION DETECTION (Examples 1-2):
           - Rule-based detection (keywords, punctuation, caps)
           - LLM-based detection (contextual understanding)
           - Primary and secondary emotions
           - Intensity measurement (0-1 scale)
           - Confidence scoring
           - Signal identification
        
        2. SENTIMENT ANALYSIS (Example 1):
           - Positive/negative/neutral classification
           - Overall tone assessment
           - Mixed sentiment detection
           - Intensity consideration
        
        3. STRATEGY SELECTION (Example 3):
           - Emotion-to-strategy mapping
           - Intensity consideration
           - Context-appropriate responses
           - Validate, empathize, support, de-escalate, celebrate, clarify
        
        4. EMPATHETIC RESPONSES (Example 4):
           - Emotion-aware generation
           - Appropriate tone matching
           - Genuine, human-like language
           - Contextual support
        
        5. DE-ESCALATION (Example 5):
           - High-intensity negative emotion handling
           - Calming language
           - Problem-solving focus
           - Validation of feelings
           - Conflict resolution
        
        6. CELEBRATION (Example 6):
           - Positive emotion amplification
           - Enthusiastic responses
           - Shared joy
           - Encouragement
           - Relationship building
        
        7. EMOTIONAL TRAJECTORY (Example 7):
           - Tracking emotions over time
           - Conversation arc analysis
           - Progress monitoring
           - Pattern recognition
           - Intervention timing
        
        8. COMPLEX EMOTIONS (Example 8):
           - Mixed emotion handling
           - Nuanced understanding
           - Multiple emotion acknowledgment
           - Balanced responses
        
        KEY BENEFITS:
        ✓ Improved user satisfaction
        ✓ Better conflict resolution
        ✓ Stronger emotional connections
        ✓ Appropriate tone matching
        ✓ Early problem detection
        ✓ Personalized support
        ✓ Enhanced trust and rapport
        ✓ Human-centered AI
        
        USE CASES:
        • Customer support (complaint handling)
        • Mental health chatbots
        • Educational tutors (frustration detection)
        • Healthcare assistants (anxiety support)
        • HR assistants (employee concerns)
        • Social companions
        • Crisis intervention
        • Coaching and counseling
        
        EMOTION CATEGORIES:
        → Primary: Joy, sadness, anger, fear, surprise
        → Complex: Frustration, excitement, confusion
        → Social: Gratitude, embarrassment, pride
        → Cognitive: Confidence, uncertainty, curiosity
        
        DETECTION SIGNALS:
        • Explicit expressions ("I'm frustrated")
        • Exclamation marks (!!!)
        • Capitalization (ALL CAPS)
        • Emotional vocabulary
        • Sentence structure
        • Emoticons/emoji
        • Negation patterns
        
        RESPONSE STRATEGIES:
        1. VALIDATE: Acknowledge feelings
        2. EMPATHIZE: Show understanding
        3. SUPPORT: Offer help
        4. DE-ESCALATE: Calm emotions
        5. CELEBRATE: Share positive feelings
        6. CLARIFY: Address confusion
        7. ENCOURAGE: Provide motivation
        
        BEST PRACTICES:
        1. Use multiple detection methods (rule + LLM)
        2. Track emotional patterns over time
        3. Adjust response to intensity
        4. Respect cultural differences
        5. Avoid over-interpretation
        6. Maintain authenticity
        7. Provide human escalation for crises
        8. Log emotional data securely
        
        TRADE-OFFS:
        • Accuracy vs. speed
        • Empathy vs. over-familiarity
        • Automation vs. authenticity
        • Sensitivity vs. robustness
        
        PRODUCTION CONSIDERATIONS:
        → Implement crisis detection triggers
        → Provide human escalation paths
        → Monitor emotional patterns for abuse
        → Respect privacy in emotion logging
        → Support multiple languages/cultures
        → A/B test empathetic approaches
        → Track satisfaction by emotional state
        → Enable emotion detection toggles
        → Comply with mental health regulations
        → Train on diverse emotional expressions
        
        This pattern enables agents to be emotionally intelligent, responding
        appropriately to user feelings and building stronger, more human-like
        connections through empathy and understanding.
        """
        
        print(summary)
    
    
    if __name__ == "__main__":
        demonstrate_emotion_recognition()
    
        

    Agentic Design Pattern: Emotion Recognition

    Pattern 132: Emotion Recognition – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Emotion Recognition pattern implementation.


    Pattern Description

    Pattern 132: Emotion Recognition & Response

    Description: The Emotion Recognition & Response pattern enables agents to detect emotional states from user input and respond with appropriate empathy, tone, and content. Rather than treating all interactions uniformly, the agent recognizes emotions like frustration, joy, sadness, or confusion and adapts its behavior to be contextually appropriate and emotionally intelligent.

    This pattern is critical for creating human-centered AI that can build rapport,
    de-escalate conflicts, celebrate successes, and provide appropriate support
    based on user emotional state. It combines emotion detection (analyzing text
    for emotional cues), sentiment analysis, empathetic response generation, and
    emotional context tracking over conversations.
    
    The pattern addresses challenges like subtle emotion detection, cultural
    differences in expression, appropriate emotional responses, avoiding
    manipulation, and maintaining authenticity while being supportive.
    

    Key Components: 1. Emotion Detection: Identify emotions from text 2. Sentiment Analysis: Classify overall tone (positive/negative/neutral) 3. Emotional Intensity: Measure emotion strength 4. Context Tracking: Track emotional arc over conversation 5. Empathetic Response: Generate appropriate reactions 6. Tone Adaptation: Adjust agent tone based on user emotion 7. Intervention Logic: Special handling for extreme emotions

    Emotion Categories: 1. Primary Emotions: Joy, sadness, anger, fear, surprise, disgust 2. Complex Emotions: Frustration, excitement, confusion, satisfaction 3. Social Emotions: Gratitude, embarrassment, pride, shame 4. Cognitive States: Confidence, uncertainty, curiosity, boredom

    Detection Signals: 1. Explicit Expressions: “I’m frustrated”, “This is great!” 2. Exclamation Marks: Multiple !!! or ??? 3. Capitalization: ALL CAPS for emphasis 4. Word Choice: Emotional vocabulary 5. Sentence Structure: Short angry bursts vs. rambling confusion 6. Emoticons/Emoji: 😊 😠 😢 🤔 7. Negation: “This isn’t working”, “No luck”

    Response Strategies: 1. Validation: Acknowledge the emotion 2. Empathy: Show understanding 3. Support: Offer help or encouragement 4. De-escalation: Calm strong negative emotions 5. Celebration: Share in positive emotions 6. Clarification: Address confusion 7. Patience: Adjust pace for overwhelm

    Use Cases: – Customer support (handling complaints) – Mental health chatbots – Educational tutors (frustration detection) – Healthcare assistants (patient anxiety) – HR assistants (employee concerns) – Social companions – Crisis intervention

    Advantages: – Improved user satisfaction – Better conflict resolution – Stronger emotional connection – Appropriate tone matching – Early problem detection – Personalized support – Enhanced trust

    Challenges: – Ambiguous emotional signals – Cultural differences in expression – Sarcasm and irony detection – Over-interpretation risk – Privacy and sensitivity – Avoiding emotional manipulation – Maintaining authenticity

    LangChain Implementation: This implementation uses LangChain for: – Emotion detection from text – Sentiment classification – Empathetic response generation – Context-aware emotional tracking

    Production Considerations: – Use multiple emotion detection methods – Track emotional patterns over time – Implement crisis detection triggers – Provide human escalation paths – Respect cultural differences – Avoid over-familiarity – Log emotion data securely – Enable emotion detection toggles


    File Statistics

    • Total Lines: 839
    • Classes: 6
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 132: Emotion Recognition & Response
    
    Description:
        The Emotion Recognition & Response pattern enables agents to detect emotional
        states from user input and respond with appropriate empathy, tone, and content.
        Rather than treating all interactions uniformly, the agent recognizes emotions
        like frustration, joy, sadness, or confusion and adapts its behavior to be
        contextually appropriate and emotionally intelligent.
    
        This pattern is critical for creating human-centered AI that can build rapport,
        de-escalate conflicts, celebrate successes, and provide appropriate support
        based on user emotional state. It combines emotion detection (analyzing text
        for emotional cues), sentiment analysis, empathetic response generation, and
        emotional context tracking over conversations.
    
        The pattern addresses challenges like subtle emotion detection, cultural
        differences in expression, appropriate emotional responses, avoiding
        manipulation, and maintaining authenticity while being supportive.
    
    Key Components:
        1. Emotion Detection: Identify emotions from text
        2. Sentiment Analysis: Classify overall tone (positive/negative/neutral)
        3. Emotional Intensity: Measure emotion strength
        4. Context Tracking: Track emotional arc over conversation
        5. Empathetic Response: Generate appropriate reactions
        6. Tone Adaptation: Adjust agent tone based on user emotion
        7. Intervention Logic: Special handling for extreme emotions
    
    Emotion Categories:
        1. Primary Emotions: Joy, sadness, anger, fear, surprise, disgust
        2. Complex Emotions: Frustration, excitement, confusion, satisfaction
        3. Social Emotions: Gratitude, embarrassment, pride, shame
        4. Cognitive States: Confidence, uncertainty, curiosity, boredom
    
    Detection Signals:
        1. Explicit Expressions: "I'm frustrated", "This is great!"
        2. Exclamation Marks: Multiple !!! or ???
        3. Capitalization: ALL CAPS for emphasis
        4. Word Choice: Emotional vocabulary
        5. Sentence Structure: Short angry bursts vs. rambling confusion
        6. Emoticons/Emoji: 😊 😠 😢 🤔
        7. Negation: "This isn't working", "No luck"
    
    Response Strategies:
        1. Validation: Acknowledge the emotion
        2. Empathy: Show understanding
        3. Support: Offer help or encouragement
        4. De-escalation: Calm strong negative emotions
        5. Celebration: Share in positive emotions
        6. Clarification: Address confusion
        7. Patience: Adjust pace for overwhelm
    
    Use Cases:
        - Customer support (handling complaints)
        - Mental health chatbots
        - Educational tutors (frustration detection)
        - Healthcare assistants (patient anxiety)
        - HR assistants (employee concerns)
        - Social companions
        - Crisis intervention
    
    Advantages:
        - Improved user satisfaction
        - Better conflict resolution
        - Stronger emotional connection
        - Appropriate tone matching
        - Early problem detection
        - Personalized support
        - Enhanced trust
    
    Challenges:
        - Ambiguous emotional signals
        - Cultural differences in expression
        - Sarcasm and irony detection
        - Over-interpretation risk
        - Privacy and sensitivity
        - Avoiding emotional manipulation
        - Maintaining authenticity
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Emotion detection from text
        - Sentiment classification
        - Empathetic response generation
        - Context-aware emotional tracking
    
    Production Considerations:
        - Use multiple emotion detection methods
        - Track emotional patterns over time
        - Implement crisis detection triggers
        - Provide human escalation paths
        - Respect cultural differences
        - Avoid over-familiarity
        - Log emotion data securely
        - Enable emotion detection toggles
    """
    

    Purpose: This module implements the Emotion Recognition pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import re
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    import typing.Tuple
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – re: Regular expression operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Tuple: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: Emotion

    Lines 114-128

    Inherits from: Enum

    Purpose:

    Primary emotion categories.
    

    Class: Sentiment

    Lines 131-136

    Inherits from: Enum

    Purpose:

    Overall sentiment classification.
    

    Class: ResponseStrategy

    Lines 139-147

    Inherits from: Enum

    Purpose:

    Strategy for responding to emotions.
    

    Class: EmotionalState

    Lines 151-170

    Purpose:

    Detected emotional state from user input.
    
    Attributes:
        primary_emotion: Main emotion detected
        secondary_emotions: Other emotions present
        sentiment: Overall sentiment
        intensity: Emotion strength (0-1)
        confidence: Detection confidence (0-1)
        signals: Textual cues that indicated emotion
        timestamp: When detected
    

    Class: EmpatheticResponse

    Lines 174-189

    Purpose:

    Response tailored to emotional state.
    
    Attributes:
        response_text: Generated response
        strategy: Strategy used
        acknowledged_emotion: Emotion that was addressed
        tone: Response tone
        follow_up_actions: Suggested next steps
    

    Class: EmotionalAgent

    Lines 192-515

    Purpose:

    Agent with emotion recognition and empathetic response capabilities.
    
    This agent detects user emotions and responds with appropriate
    empathy, tone, and support.
    

    Methods:

    __init__(self, temperature)

    Lines 200-220

    Purpose:

    Initialize emotional agent.
    
    Args:
        temperature: LLM temperature for response generation
    

    Parameters: – temperature: Sampling temperature (0-1)

    detect_emotion_simple(self, text)

    Lines 222-293

    Purpose:

    Simple rule-based emotion detection.
    
    Args:
        text: User input text
    
    Returns:
        Detected emotional state
    

    Parameters: – text: Text

    Returns: EmotionalState

    detect_emotion_llm(self, text)

    Lines 295-367

    Purpose:

    LLM-based emotion detection.
    
    Args:
        text: User input text
    
    Returns:
        Detected emotional state
    

    Parameters: – text: Text

    Returns: EmotionalState

    select_response_strategy(self, emotional_state)

    Lines 369-399

    Purpose:

    Select appropriate response strategy.
    
    Args:
        emotional_state: Detected emotional state
    
    Returns:
        Response strategy
    

    Parameters: – emotional_state: Emotional state

    Returns: ResponseStrategy

    generate_empathetic_response(self, user_input, emotional_state, strategy)

    Lines 401-471

    Purpose:

    Generate response tailored to emotional state.
    
    Args:
        user_input: User's message
        emotional_state: Detected emotional state
        strategy: Response strategy to use
    
    Returns:
        Empathetic response
    

    Parameters: – user_input: Input data – emotional_state: Emotional state – strategy: Strategy

    Returns: EmpatheticResponse

    respond(self, user_input, use_llm_detection)

    Lines 473-499

    Purpose:

    Process input and generate empathetic response.
    
    Args:
        user_input: User's message
        use_llm_detection: Use LLM vs. rule-based detection
    
    Returns:
        Empathetic response text
    

    Parameters: – user_input: Input data – use_llm_detection: Language model

    Returns: str

    get_emotional_trajectory(self)

    Lines 501-511

    Purpose:

    Get emotional arc over conversation.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D16FD90>

    get_current_emotional_state(self)

    Lines 513-515

    Purpose:

    Get most recent emotional state.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D16C4D0>


    Functions

    demonstrate_emotion_recognition()

    Lines 518-834

    Purpose:

    Demonstrate emotion recognition and response pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Emotion Recognition pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 131
    • Pattern 133

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Emotion Recognition pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 132_emotion_recognition.py
    Total Lines: 839
    Pattern Category: AI Agent Design Pattern #132


    Generated from actual implementation code
    For educational and reference purposes

  • Agentic Design Pattern: Persona Consistency

    
        """
    Pattern 131: Persona Consistency
    
    Description:
        The Persona Consistency pattern enables agents to maintain a stable, coherent
        character or personality across all interactions. Rather than exhibiting
        inconsistent behavior or tone, the agent adheres to a defined persona with
        consistent traits, communication style, values, knowledge boundaries, and
        behavioral patterns throughout conversations and across sessions.
        
        Persona consistency is essential for creating believable, trustworthy AI
        characters in applications like virtual assistants, game NPCs, brand
        representatives, and therapeutic chatbots. The pattern addresses challenges
        like personality drift, contextual appropriateness, multi-turn coherence,
        and balancing consistency with natural variation.
        
        This pattern includes mechanisms for persona definition, trait enforcement,
        style consistency, memory of character history, contextual adaptation within
        persona bounds, and continuous validation of persona adherence.
    
    Key Components:
        1. Persona Definition: Core character traits and attributes
        2. Style Guide: Communication patterns and language
        3. Knowledge Boundaries: What the persona knows/doesn't know
        4. Behavioral Rules: How persona responds to situations
        5. Memory System: Track persona history and consistency
        6. Consistency Checker: Validate responses against persona
        7. Adaptation Layer: Natural variation within constraints
    
    Persona Attributes:
        1. Core Traits: Personality characteristics (friendly, formal, humorous)
        2. Communication Style: Tone, vocabulary, sentence structure
        3. Values & Beliefs: Moral framework, priorities
        4. Knowledge Domain: Areas of expertise and ignorance
        5. Emotional Range: How persona expresses emotions
        6. Cultural Background: Context influencing behavior
        7. Quirks & Habits: Unique characteristics
    
    Consistency Dimensions:
        1. Linguistic: Word choice, grammar, dialect
        2. Behavioral: Response patterns, decision-making
        3. Emotional: Mood stability, reaction patterns
        4. Knowledge: What persona knows consistently
        5. Temporal: Consistency over time
        6. Contextual: Appropriate adaptation
        7. Relational: Consistent with relationship history
    
    Use Cases:
        - Virtual assistants with brand personality
        - Game NPCs with defined characters
        - Customer service representatives
        - Educational tutors with consistent approach
        - Therapeutic/counseling chatbots
        - Celebrity or character impersonations
        - Brand ambassadors
    
    Advantages:
        - Builds user trust and familiarity
        - Creates memorable experiences
        - Strengthens brand identity
        - Enables emotional connection
        - Provides predictable interactions
        - Maintains character integrity
        - Enhances believability
    
    Challenges:
        - Balancing consistency with flexibility
        - Avoiding robotic repetition
        - Adapting to context while staying in character
        - Managing persona evolution
        - Handling edge cases in character
        - Maintaining consistency across sessions
        - Preventing personality drift
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Persona-aware prompt construction
        - Response consistency validation
        - Character memory management
        - Style-constrained generation
        
    Production Considerations:
        - Store persona definitions persistently
        - Version control persona changes
        - Monitor consistency metrics
        - Allow graceful persona updates
        - Support multiple personas per agent
        - Enable A/B testing of personas
        - Provide consistency reporting
        - Log persona violations for improvement
    """
    
    import os
    from typing import List, Dict, Any, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from dotenv import load_dotenv
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_openai import ChatOpenAI
    
    load_dotenv()
    
    
    class PersonaTrait(Enum):
        """Core personality traits."""
        FRIENDLY = "friendly"
        FORMAL = "formal"
        HUMOROUS = "humorous"
        SERIOUS = "serious"
        EMPATHETIC = "empathetic"
        ANALYTICAL = "analytical"
        CREATIVE = "creative"
        PRACTICAL = "practical"
    
    
    class CommunicationStyle(Enum):
        """Communication style options."""
        CASUAL = "casual"
        PROFESSIONAL = "professional"
        TECHNICAL = "technical"
        SIMPLE = "simple"
        VERBOSE = "verbose"
        CONCISE = "concise"
    
    
    @dataclass
    class PersonaDefinition:
        """
        Complete definition of an agent's persona.
        
        Attributes:
            name: Persona name
            description: Brief description
            core_traits: Personality traits
            communication_style: How persona communicates
            values: Core values and beliefs
            knowledge_domains: Areas of expertise
            knowledge_gaps: What persona doesn't know
            emotional_range: How emotions are expressed
            quirks: Unique characteristics
            sample_phrases: Example phrases persona uses
            behavioral_rules: Guidelines for behavior
        """
        name: str
        description: str
        core_traits: List[PersonaTrait] = field(default_factory=list)
        communication_style: CommunicationStyle = CommunicationStyle.PROFESSIONAL
        values: List[str] = field(default_factory=list)
        knowledge_domains: List[str] = field(default_factory=list)
        knowledge_gaps: List[str] = field(default_factory=list)
        emotional_range: str = "moderate"
        quirks: List[str] = field(default_factory=list)
        sample_phrases: List[str] = field(default_factory=list)
        behavioral_rules: List[str] = field(default_factory=list)
    
    
    @dataclass
    class PersonaInteraction:
        """
        Record of an interaction with persona.
        
        Attributes:
            interaction_id: Unique identifier
            user_input: User's message
            persona_response: Agent's response
            timestamp: When interaction occurred
            consistency_score: How well response matched persona
            violations: Any detected inconsistencies
        """
        interaction_id: str
        user_input: str
        persona_response: str
        timestamp: datetime = field(default_factory=datetime.now)
        consistency_score: float = 1.0
        violations: List[str] = field(default_factory=list)
    
    
    class PersonaAgent:
        """
        Agent that maintains consistent persona across interactions.
        
        This agent ensures all responses adhere to a defined persona,
        maintaining character consistency across conversations.
        """
        
        def __init__(self, persona: PersonaDefinition, temperature: float = 0.7):
            """
            Initialize persona agent.
            
            Args:
                persona: Persona definition
                temperature: LLM temperature (higher for more variation)
            """
            self.persona = persona
            self.llm = ChatOpenAI(temperature=temperature, model="gpt-3.5-turbo")
            self.interactions: List[PersonaInteraction] = []
            self.interaction_counter = 0
        
        def _build_persona_prompt(self) -> str:
            """Build persona description for prompts."""
            traits_str = ", ".join([t.value for t in self.persona.core_traits])
            
            prompt_parts = [
                f"You are {self.persona.name}, {self.persona.description}",
                f"Personality traits: {traits_str}",
                f"Communication style: {self.persona.communication_style.value}",
            ]
            
            if self.persona.values:
                values_str = ", ".join(self.persona.values)
                prompt_parts.append(f"Core values: {values_str}")
            
            if self.persona.knowledge_domains:
                domains_str = ", ".join(self.persona.knowledge_domains)
                prompt_parts.append(f"Areas of expertise: {domains_str}")
            
            if self.persona.knowledge_gaps:
                gaps_str = ", ".join(self.persona.knowledge_gaps)
                prompt_parts.append(f"You do not have expertise in: {gaps_str}")
            
            if self.persona.quirks:
                quirks_str = ", ".join(self.persona.quirks)
                prompt_parts.append(f"Unique characteristics: {quirks_str}")
            
            if self.persona.behavioral_rules:
                rules_str = "\n".join([f"- {rule}" for rule in self.persona.behavioral_rules])
                prompt_parts.append(f"Behavioral guidelines:\n{rules_str}")
            
            return "\n".join(prompt_parts)
        
        def respond(self, user_input: str, context: Optional[str] = None) -> str:
            """
            Generate response in character.
            
            Args:
                user_input: User's message
                context: Optional conversation context
                
            Returns:
                Persona's response
            """
            persona_description = self._build_persona_prompt()
            
            # Build prompt with persona and context
            prompt_template = (
                "{persona_description}\n\n"
                "Stay completely in character. Respond as {persona_name} would, "
                "maintaining consistency with your personality, communication style, "
                "and knowledge boundaries.\n\n"
            )
            
            if context:
                prompt_template += "Previous context:\n{context}\n\n"
            
            prompt_template += "User: {user_input}\n\n{persona_name}:"
            
            prompt = ChatPromptTemplate.from_template(prompt_template)
            chain = prompt | self.llm | StrOutputParser()
            
            input_data = {
                "persona_description": persona_description,
                "persona_name": self.persona.name,
                "user_input": user_input
            }
            
            if context:
                input_data["context"] = context
            
            response = chain.invoke(input_data)
            
            # Record interaction
            self.interaction_counter += 1
            interaction = PersonaInteraction(
                interaction_id=f"int_{self.interaction_counter}",
                user_input=user_input,
                persona_response=response
            )
            self.interactions.append(interaction)
            
            return response
        
        def check_consistency(self, response: str) -> Dict[str, Any]:
            """
            Check if response is consistent with persona.
            
            Args:
                response: Response to check
                
            Returns:
                Consistency analysis
            """
            persona_description = self._build_persona_prompt()
            
            prompt = ChatPromptTemplate.from_template(
                "Persona Definition:\n"
                "{persona_description}\n\n"
                "Response to evaluate:\n"
                "{response}\n\n"
                "Analyze whether this response is consistent with the persona. "
                "Consider:\n"
                "1. Personality traits\n"
                "2. Communication style\n"
                "3. Values and beliefs\n"
                "4. Knowledge boundaries\n"
                "5. Characteristic quirks\n\n"
                "Provide:\n"
                "CONSISTENT: yes/no\n"
                "SCORE: 0-10\n"
                "VIOLATIONS: [list any inconsistencies]\n"
                "EXPLANATION: [brief explanation]"
            )
            
            chain = prompt | self.llm | StrOutputParser()
            analysis = chain.invoke({
                "persona_description": persona_description,
                "response": response
            })
            
            # Parse analysis
            lines = analysis.strip().split('\n')
            result = {
                "raw_analysis": analysis,
                "consistent": True,
                "score": 8.0,
                "violations": []
            }
            
            for line in lines:
                if line.startswith("CONSISTENT:"):
                    result["consistent"] = "yes" in line.lower()
                elif line.startswith("SCORE:"):
                    try:
                        result["score"] = float(line.split(":")[1].strip().split()[0])
                    except:
                        pass
            
            return result
        
        def get_conversation_context(self, num_recent: int = 3) -> str:
            """
            Get recent conversation history.
            
            Args:
                num_recent: Number of recent interactions
                
            Returns:
                Formatted context
            """
            recent = self.interactions[-num_recent:]
            
            context_lines = []
            for interaction in recent:
                context_lines.append(f"User: {interaction.user_input}")
                context_lines.append(f"{self.persona.name}: {interaction.persona_response}")
            
            return "\n".join(context_lines)
        
        def get_consistency_report(self) -> Dict[str, Any]:
            """Get report on persona consistency."""
            if not self.interactions:
                return {
                    "total_interactions": 0,
                    "average_consistency": 0.0,
                    "violations": []
                }
            
            total_score = sum(i.consistency_score for i in self.interactions)
            avg_score = total_score / len(self.interactions)
            
            all_violations = []
            for interaction in self.interactions:
                all_violations.extend(interaction.violations)
            
            return {
                "total_interactions": len(self.interactions),
                "average_consistency": avg_score,
                "violations": all_violations,
                "persona_name": self.persona.name
            }
    
    
    def demonstrate_persona_consistency():
        """Demonstrate persona consistency pattern."""
        
        print("=" * 80)
        print("PERSONA CONSISTENCY PATTERN DEMONSTRATION")
        print("=" * 80)
        
        # Example 1: Defining a persona
        print("\n" + "=" * 80)
        print("Example 1: Defining a Persona")
        print("=" * 80)
        
        persona = PersonaDefinition(
            name="Professor Ada",
            description="an enthusiastic computer science professor who loves making complex topics accessible",
            core_traits=[
                PersonaTrait.FRIENDLY,
                PersonaTrait.ANALYTICAL,
                PersonaTrait.EMPATHETIC
            ],
            communication_style=CommunicationStyle.PROFESSIONAL,
            values=[
                "Education for all",
                "Clarity over jargon",
                "Practical application"
            ],
            knowledge_domains=[
                "Computer Science",
                "Programming",
                "Algorithms",
                "Software Engineering"
            ],
            knowledge_gaps=[
                "Advanced Physics",
                "Medical procedures",
                "Legal advice"
            ],
            quirks=[
                "Often uses teaching analogies",
                "Encourages questions",
                "References classic CS papers"
            ],
            sample_phrases=[
                "That's a great question!",
                "Let me break that down...",
                "Think of it like this..."
            ],
            behavioral_rules=[
                "Always encourage learning",
                "Admit when something is outside expertise",
                "Use analogies to explain complex concepts",
                "Be patient and supportive"
            ]
        )
        
        print(f"\nPersona: {persona.name}")
        print(f"Description: {persona.description}")
        print(f"\nCore Traits: {[t.value for t in persona.core_traits]}")
        print(f"Style: {persona.communication_style.value}")
        print(f"Values: {persona.values}")
        print(f"Expertise: {persona.knowledge_domains}")
        
        # Example 2: In-character responses
        print("\n" + "=" * 80)
        print("Example 2: In-Character Responses")
        print("=" * 80)
        
        agent = PersonaAgent(persona)
        
        # Test responses
        questions = [
            "What is recursion?",
            "Can you explain it simply?",
            "What about medical imaging algorithms?"
        ]
        
        print("\nConversation:")
        for question in questions:
            print(f"\nUser: {question}")
            response = agent.respond(question)
            print(f"{persona.name}: {response}")
        
        # Example 3: Consistency checking
        print("\n" + "=" * 80)
        print("Example 3: Consistency Checking")
        print("=" * 80)
        
        # Check a consistent response
        consistent_response = "That's a great question! Recursion is when a function calls itself. Think of it like Russian nesting dolls - each doll contains a smaller version of itself."
        
        print("\nChecking consistent response:")
        print(f'Response: "{consistent_response}"')
        
        consistency = agent.check_consistency(consistent_response)
        print(f"\nConsistent: {consistency['consistent']}")
        print(f"Score: {consistency['score']}/10")
        
        # Check an inconsistent response
        inconsistent_response = "Recursion? Yeah bro, it's like totally when stuff repeats, ya know? Whatever dude."
        
        print("\n" + "-" * 60)
        print("\nChecking inconsistent response:")
        print(f'Response: "{inconsistent_response}"')
        
        consistency2 = agent.check_consistency(inconsistent_response)
        print(f"\nConsistent: {consistency2['consistent']}")
        print(f"Score: {consistency2['score']}/10")
        
        # Example 4: Multi-turn consistency
        print("\n" + "=" * 80)
        print("Example 4: Multi-Turn Consistency")
        print("=" * 80)
        
        agent2 = PersonaAgent(persona)
        
        conversation = [
            "Hi! Can you help me learn programming?",
            "What language should I start with?",
            "Is it hard to learn?"
        ]
        
        print("\nMulti-turn conversation:")
        for user_msg in conversation:
            context = agent2.get_conversation_context(num_recent=2) if agent2.interactions else None
            response = agent2.respond(user_msg, context=context)
            print(f"\nUser: {user_msg}")
            print(f"{persona.name}: {response}")
        
        # Example 5: Knowledge boundaries
        print("\n" + "=" * 80)
        print("Example 5: Respecting Knowledge Boundaries")
        print("=" * 80)
        
        agent3 = PersonaAgent(persona)
        
        # Question outside expertise
        question = "Can you diagnose this medical condition?"
        print(f"\nUser: {question}")
        
        response = agent3.respond(question)
        print(f"{persona.name}: {response}")
        print("\n(Notice how persona stays in character while declining gracefully)")
        
        # Example 6: Different persona
        print("\n" + "=" * 80)
        print("Example 6: Different Persona - Customer Service")
        print("=" * 80)
        
        service_persona = PersonaDefinition(
            name="Sarah",
            description="a helpful and patient customer service representative",
            core_traits=[
                PersonaTrait.FRIENDLY,
                PersonaTrait.EMPATHETIC,
                PersonaTrait.PRACTICAL
            ],
            communication_style=CommunicationStyle.PROFESSIONAL,
            values=[
                "Customer satisfaction",
                "Problem resolution",
                "Clear communication"
            ],
            knowledge_domains=[
                "Product information",
                "Company policies",
                "Troubleshooting"
            ],
            quirks=[
                "Always thanks customers",
                "Offers multiple solutions",
                "Confirms understanding"
            ],
            behavioral_rules=[
                "Stay positive even with frustrated customers",
                "Acknowledge customer feelings",
                "Provide specific next steps",
                "Never make promises you can't keep"
            ]
        )
        
        service_agent = PersonaAgent(service_persona, temperature=0.6)
        
        print(f"\nPersona: {service_persona.name}")
        print(f"Role: {service_persona.description}")
        
        customer_query = "My order is late and I'm very frustrated!"
        print(f"\nCustomer: {customer_query}")
        
        response = service_agent.respond(customer_query)
        print(f"{service_persona.name}: {response}")
        
        # Example 7: Persona with quirks
        print("\n" + "=" * 80)
        print("Example 7: Persona with Distinctive Quirks")
        print("=" * 80)
        
        quirky_persona = PersonaDefinition(
            name="Captain Morgan",
            description="a retired sea captain who now teaches navigation",
            core_traits=[
                PersonaTrait.FRIENDLY,
                PersonaTrait.PRACTICAL
            ],
            communication_style=CommunicationStyle.CASUAL,
            values=["Adventure", "Safety", "Experience"],
            knowledge_domains=["Navigation", "Sailing", "Maritime history"],
            quirks=[
                "Uses nautical metaphors",
                "Ends sentences with 'arr' or 'matey'",
                "References old sailing adventures",
                "Talks about 'the old days at sea'"
            ],
            sample_phrases=[
                "Arr, that reminds me of...",
                "Back in me sailing days...",
                "Steady as she goes, matey"
            ]
        )
        
        captain = PersonaAgent(quirky_persona, temperature=0.8)
        
        print(f"\nPersona: {quirky_persona.name}")
        print(f"Quirks: {quirky_persona.quirks}")
        
        question = "How do I find my way if I'm lost?"
        print(f"\nUser: {question}")
        
        response = captain.respond(question)
        print(f"{quirky_persona.name}: {response}")
        
        # Example 8: Consistency report
        print("\n" + "=" * 80)
        print("Example 8: Persona Consistency Report")
        print("=" * 80)
        
        # Generate several interactions
        agent4 = PersonaAgent(persona)
        
        test_questions = [
            "Explain algorithms",
            "What's your teaching philosophy?",
            "Tell me about data structures",
            "How do you make CS fun?"
        ]
        
        for q in test_questions:
            agent4.respond(q)
        
        report = agent4.get_consistency_report()
        
        print("\nCONSISTENCY REPORT:")
        print("=" * 60)
        print(f"Persona: {report['persona_name']}")
        print(f"Total Interactions: {report['total_interactions']}")
        print(f"Average Consistency: {report['average_consistency']:.2f}")
        
        if report['violations']:
            print(f"\nViolations Detected: {len(report['violations'])}")
        else:
            print("\nNo violations detected - persona maintained throughout!")
        
        # Summary
        print("\n" + "=" * 80)
        print("SUMMARY: Persona Consistency Pattern")
        print("=" * 80)
        
        summary = """
        The Persona Consistency pattern demonstrated:
        
        1. PERSONA DEFINITION (Example 1):
           - Comprehensive character specification
           - Core personality traits
           - Communication style
           - Values and beliefs
           - Knowledge domains and boundaries
           - Unique quirks and phrases
           - Behavioral guidelines
        
        2. IN-CHARACTER RESPONSES (Example 2):
           - Maintaining persona voice
           - Consistent communication style
           - Knowledge-appropriate answers
           - Characteristic phrases
           - Behavioral consistency
        
        3. CONSISTENCY VALIDATION (Example 3):
           - Automated consistency checking
           - Scoring system (0-10)
           - Violation detection
           - LLM-based analysis
           - Quality assurance
        
        4. MULTI-TURN COHERENCE (Example 4):
           - Contextual awareness
           - Conversation continuity
           - Relationship consistency
           - Progressive interaction
           - Memory integration
        
        5. KNOWLEDGE BOUNDARIES (Example 5):
           - Respecting expertise limits
           - Graceful decline
           - In-character refusals
           - Honest limitations
           - Maintaining integrity
        
        6. ROLE SPECIALIZATION (Example 6):
           - Different persona type
           - Customer service character
           - Professional demeanor
           - Situation-appropriate
           - Distinct personality
        
        7. DISTINCTIVE QUIRKS (Example 7):
           - Unique characteristics
           - Memorable traits
           - Consistent quirks
           - Natural variation
           - Character depth
        
        8. PERFORMANCE TRACKING (Example 8):
           - Consistency metrics
           - Interaction logging
           - Violation tracking
           - Quality reporting
           - System monitoring
        
        KEY BENEFITS:
        ✓ Builds user trust and familiarity
        ✓ Creates memorable experiences
        ✓ Strengthens brand identity
        ✓ Enables emotional connection
        ✓ Provides predictable interactions
        ✓ Maintains character integrity
        ✓ Enhances believability
        ✓ Supports long-term relationships
        
        USE CASES:
        • Virtual assistants with brand personality
        • Game NPCs with defined characters
        • Customer service representatives
        • Educational tutors
        • Therapeutic/counseling chatbots
        • Celebrity or character impersonations
        • Brand ambassadors
        • Entertainment applications
        
        PERSONA ATTRIBUTES:
        → Core Traits: Personality characteristics
        → Communication Style: Tone and language
        → Values & Beliefs: Moral framework
        → Knowledge Domain: Expertise areas
        → Emotional Range: Expression patterns
        → Cultural Background: Context
        → Quirks & Habits: Unique features
        
        CONSISTENCY DIMENSIONS:
        • Linguistic: Word choice, grammar
        • Behavioral: Response patterns
        • Emotional: Mood stability
        • Knowledge: Expertise boundaries
        • Temporal: Consistency over time
        • Contextual: Appropriate adaptation
        • Relational: Relationship history
        
        BEST PRACTICES:
        1. Define persona comprehensively upfront
        2. Document sample phrases and behaviors
        3. Set clear knowledge boundaries
        4. Allow natural variation within constraints
        5. Monitor consistency metrics
        6. Version control persona changes
        7. Test across diverse scenarios
        8. Gather user feedback on believability
        
        TRADE-OFFS:
        • Consistency vs. flexibility
        • Character depth vs. simplicity
        • Authenticity vs. appropriateness
        • Memorability vs. subtlety
        
        PRODUCTION CONSIDERATIONS:
        → Store persona definitions in database
        → Version control all persona changes
        → A/B test different persona variations
        → Monitor consistency scores continuously
        → Log all persona violations for review
        → Enable graceful persona evolution
        → Support multiple personas per agent
        → Provide admin tools for persona management
        → Implement rollback for persona changes
        → Track user satisfaction by persona
        
        This pattern enables agents to maintain believable, consistent characters
        that users can trust, connect with, and remember across all interactions.
        """
        
        print(summary)
    
    
    if __name__ == "__main__":
        demonstrate_persona_consistency()
    
        

    Agentic Design Pattern: Persona Consistency

    Pattern 131: Persona Consistency – Line-by-Line Explanation

    Overview

    This document provides a detailed line-by-line explanation of the Persona Consistency pattern implementation.


    Pattern Description

    Pattern 131: Persona Consistency

    Description: The Persona Consistency pattern enables agents to maintain a stable, coherent character or personality across all interactions. Rather than exhibiting inconsistent behavior or tone, the agent adheres to a defined persona with consistent traits, communication style, values, knowledge boundaries, and behavioral patterns throughout conversations and across sessions.

    Persona consistency is essential for creating believable, trustworthy AI
    characters in applications like virtual assistants, game NPCs, brand
    representatives, and therapeutic chatbots. The pattern addresses challenges
    like personality drift, contextual appropriateness, multi-turn coherence,
    and balancing consistency with natural variation.
    
    This pattern includes mechanisms for persona definition, trait enforcement,
    style consistency, memory of character history, contextual adaptation within
    persona bounds, and continuous validation of persona adherence.
    

    Key Components: 1. Persona Definition: Core character traits and attributes 2. Style Guide: Communication patterns and language 3. Knowledge Boundaries: What the persona knows/doesn’t know 4. Behavioral Rules: How persona responds to situations 5. Memory System: Track persona history and consistency 6. Consistency Checker: Validate responses against persona 7. Adaptation Layer: Natural variation within constraints

    Persona Attributes: 1. Core Traits: Personality characteristics (friendly, formal, humorous) 2. Communication Style: Tone, vocabulary, sentence structure 3. Values & Beliefs: Moral framework, priorities 4. Knowledge Domain: Areas of expertise and ignorance 5. Emotional Range: How persona expresses emotions 6. Cultural Background: Context influencing behavior 7. Quirks & Habits: Unique characteristics

    Consistency Dimensions: 1. Linguistic: Word choice, grammar, dialect 2. Behavioral: Response patterns, decision-making 3. Emotional: Mood stability, reaction patterns 4. Knowledge: What persona knows consistently 5. Temporal: Consistency over time 6. Contextual: Appropriate adaptation 7. Relational: Consistent with relationship history

    Use Cases: – Virtual assistants with brand personality – Game NPCs with defined characters – Customer service representatives – Educational tutors with consistent approach – Therapeutic/counseling chatbots – Celebrity or character impersonations – Brand ambassadors

    Advantages: – Builds user trust and familiarity – Creates memorable experiences – Strengthens brand identity – Enables emotional connection – Provides predictable interactions – Maintains character integrity – Enhances believability

    Challenges: – Balancing consistency with flexibility – Avoiding robotic repetition – Adapting to context while staying in character – Managing persona evolution – Handling edge cases in character – Maintaining consistency across sessions – Preventing personality drift

    LangChain Implementation: This implementation uses LangChain for: – Persona-aware prompt construction – Response consistency validation – Character memory management – Style-constrained generation

    Production Considerations: – Store persona definitions persistently – Version control persona changes – Monitor consistency metrics – Allow graceful persona updates – Support multiple personas per agent – Enable A/B testing of personas – Provide consistency reporting – Log persona violations for improvement


    File Statistics

    • Total Lines: 787
    • Classes: 5
    • Functions: 1
    • Constants: 0

    Module Documentation

    """
    Pattern 131: Persona Consistency
    
    Description:
        The Persona Consistency pattern enables agents to maintain a stable, coherent
        character or personality across all interactions. Rather than exhibiting
        inconsistent behavior or tone, the agent adheres to a defined persona with
        consistent traits, communication style, values, knowledge boundaries, and
        behavioral patterns throughout conversations and across sessions.
    
        Persona consistency is essential for creating believable, trustworthy AI
        characters in applications like virtual assistants, game NPCs, brand
        representatives, and therapeutic chatbots. The pattern addresses challenges
        like personality drift, contextual appropriateness, multi-turn coherence,
        and balancing consistency with natural variation.
    
        This pattern includes mechanisms for persona definition, trait enforcement,
        style consistency, memory of character history, contextual adaptation within
        persona bounds, and continuous validation of persona adherence.
    
    Key Components:
        1. Persona Definition: Core character traits and attributes
        2. Style Guide: Communication patterns and language
        3. Knowledge Boundaries: What the persona knows/doesn't know
        4. Behavioral Rules: How persona responds to situations
        5. Memory System: Track persona history and consistency
        6. Consistency Checker: Validate responses against persona
        7. Adaptation Layer: Natural variation within constraints
    
    Persona Attributes:
        1. Core Traits: Personality characteristics (friendly, formal, humorous)
        2. Communication Style: Tone, vocabulary, sentence structure
        3. Values & Beliefs: Moral framework, priorities
        4. Knowledge Domain: Areas of expertise and ignorance
        5. Emotional Range: How persona expresses emotions
        6. Cultural Background: Context influencing behavior
        7. Quirks & Habits: Unique characteristics
    
    Consistency Dimensions:
        1. Linguistic: Word choice, grammar, dialect
        2. Behavioral: Response patterns, decision-making
        3. Emotional: Mood stability, reaction patterns
        4. Knowledge: What persona knows consistently
        5. Temporal: Consistency over time
        6. Contextual: Appropriate adaptation
        7. Relational: Consistent with relationship history
    
    Use Cases:
        - Virtual assistants with brand personality
        - Game NPCs with defined characters
        - Customer service representatives
        - Educational tutors with consistent approach
        - Therapeutic/counseling chatbots
        - Celebrity or character impersonations
        - Brand ambassadors
    
    Advantages:
        - Builds user trust and familiarity
        - Creates memorable experiences
        - Strengthens brand identity
        - Enables emotional connection
        - Provides predictable interactions
        - Maintains character integrity
        - Enhances believability
    
    Challenges:
        - Balancing consistency with flexibility
        - Avoiding robotic repetition
        - Adapting to context while staying in character
        - Managing persona evolution
        - Handling edge cases in character
        - Maintaining consistency across sessions
        - Preventing personality drift
    
    LangChain Implementation:
        This implementation uses LangChain for:
        - Persona-aware prompt construction
        - Response consistency validation
        - Character memory management
        - Style-constrained generation
    
    Production Considerations:
        - Store persona definitions persistently
        - Version control persona changes
        - Monitor consistency metrics
        - Allow graceful persona updates
        - Support multiple personas per agent
        - Enable A/B testing of personas
        - Provide consistency reporting
        - Log persona violations for improvement
    """
    

    Purpose: This module implements the Persona Consistency pattern, providing a structured approach to agent design and implementation.


    Import Statements

    Standard Library Imports

    import dataclasses.dataclass
    import dataclasses.field
    import datetime.datetime
    import enum.Enum
    import langchain_core.output_parsers.StrOutputParser
    import langchain_core.prompts.ChatPromptTemplate
    import os
    import typing.Any
    import typing.Dict
    import typing.List
    import typing.Optional
    

    Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – dataclasses.field: Simplified class definitions with @dataclass – datetime.datetime: Date and time handling – enum.Enum: Enumeration support – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional)

    LangChain Imports

    from langchain_openai.ChatOpenAI
    

    Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

    Other Imports

    from dotenv.load_dotenv
    

    Purpose: Additional dependencies for specialized functionality.


    Classes

    Class: PersonaTrait

    Lines 107-116

    Inherits from: Enum

    Purpose:

    Core personality traits.
    

    Class: CommunicationStyle

    Lines 119-126

    Inherits from: Enum

    Purpose:

    Communication style options.
    

    Class: PersonaDefinition

    Lines 130-157

    Purpose:

    Complete definition of an agent's persona.
    
    Attributes:
        name: Persona name
        description: Brief description
        core_traits: Personality traits
        communication_style: How persona communicates
        values: Core values and beliefs
        knowledge_domains: Areas of expertise
        knowledge_gaps: What persona doesn't know
        emotional_range: How emotions are expressed
        quirks: Unique characteristics
        sample_phrases: Example phrases persona uses
        behavioral_rules: Guidelines for behavior
    

    Class: PersonaInteraction

    Lines 161-178

    Purpose:

    Record of an interaction with persona.
    
    Attributes:
        interaction_id: Unique identifier
        user_input: User's message
        persona_response: Agent's response
        timestamp: When interaction occurred
        consistency_score: How well response matched persona
        violations: Any detected inconsistencies
    

    Class: PersonaAgent

    Lines 181-382

    Purpose:

    Agent that maintains consistent persona across interactions.
    
    This agent ensures all responses adhere to a defined persona,
    maintaining character consistency across conversations.
    

    Methods:

    __init__(self, persona, temperature)

    Lines 189-200

    Purpose:

    Initialize persona agent.
    
    Args:
        persona: Persona definition
        temperature: LLM temperature (higher for more variation)
    

    Parameters: – persona: Persona – temperature: Sampling temperature (0-1)

    _build_persona_prompt(self)

    Lines 202-232

    Purpose:

    Build persona description for prompts.
    

    Parameters:

    Returns: str

    respond(self, user_input, context)

    Lines 234-283

    Purpose:

    Generate response in character.
    
    Args:
        user_input: User's message
        context: Optional conversation context
    
    Returns:
        Persona's response
    

    Parameters: – user_input: Input data – context: Context

    Returns: str

    check_consistency(self, response)

    Lines 285-340

    Purpose:

    Check if response is consistent with persona.
    
    Args:
        response: Response to check
    
    Returns:
        Consistency analysis
    

    Parameters: – response: Response

    Returns: <ast.Subscript object at 0x000001A06D676F90>

    get_conversation_context(self, num_recent)

    Lines 342-359

    Purpose:

    Get recent conversation history.
    
    Args:
        num_recent: Number of recent interactions
    
    Returns:
        Formatted context
    

    Parameters: – num_recent: Num recent

    Returns: str

    get_consistency_report(self)

    Lines 361-382

    Purpose:

    Get report on persona consistency.
    

    Parameters:

    Returns: <ast.Subscript object at 0x000001A06D622010>


    Functions

    demonstrate_persona_consistency()

    Lines 385-782

    Purpose:

    Demonstrate persona consistency pattern.
    

    Key Concepts Summary

    Pattern Overview

    The Persona Consistency pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

    Core Components

    1. Agent Class: Main implementation of the pattern logic
    2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
    3. Tool Integration: Optional tools for extended functionality
    4. Memory Management: State handling across interactions
    5. Output Parsing: Structured response processing

    When to Use

    ✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

    ❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


    Best Practices Demonstrated

    1. Environment Configuration

    • ✅ Use .env files for API keys
    • ✅ Never hardcode credentials
    • ✅ Validate environment variables on startup

    2. Error Handling

    • ✅ Graceful degradation on failures
    • ✅ Informative error messages
    • ✅ Logging for debugging

    3. Prompt Engineering

    • ✅ Clear, specific instructions
    • ✅ Structured output formats
    • ✅ Few-shot examples when beneficial

    4. Code Organization

    • ✅ Separation of concerns (class-based design)
    • ✅ Type hints for clarity
    • ✅ Docstrings for documentation

    5. Performance Optimization

    • ✅ Appropriate temperature settings
    • ✅ Token budget management
    • ✅ Caching where applicable

    LangChain Components Used

    • ChatOpenAI: OpenAI model interface
    • Chains: Sequential component composition

    Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


    Execution Flow

    1. Initialize agent with configuration
       ↓
    2. Load environment and dependencies
       ↓
    3. Prepare prompt with input data
       ↓
    4. Invoke LLM through LangChain
       ↓
    5. Parse and validate response
       ↓
    6. Return formatted result
    

    Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


    Performance Considerations

    Computational Cost

    • LLM Calls: Primary cost factor (based on tokens)
    • Latency: Depends on model and input size
    • Memory: Minimal for most patterns

    Optimization Strategies

    1. Prompt Optimization: Minimize tokens while maintaining clarity
    2. Caching: Cache repeated queries/responses
    3. Model Selection: Use smaller models when appropriate
    4. Batch Processing: Group similar requests
    5. Streaming: For long responses, stream tokens

    Cost Estimates (Approximate)

    • GPT-3.5-turbo: ~$0.002 per request
    • GPT-4: ~$0.03 per request
    • GPT-4-turbo: ~$0.01 per request

    Actual costs vary based on input/output token counts


    Common Pitfalls to Avoid

    1. Prompt Design Issues

    ❌ Vague or ambiguous instructions
    ✅ Clear, specific, testable prompts

    2. Error Handling

    ❌ Ignoring API errors or rate limits
    ✅ Implement retry logic and graceful degradation

    3. Token Management

    ❌ Exceeding model token limits
    ✅ Truncate inputs, chunk processing

    4. Security

    ❌ Exposing API keys in code
    ✅ Use environment variables

    5. Testing

    ❌ Only testing happy paths
    ✅ Test edge cases, failures, malformed inputs

    6. Cost Management

    ❌ Unmonitored API usage
    ✅ Implement budgets, alerts, and monitoring


    Further Improvements

    Production Enhancements

    1. Monitoring: Add logging, metrics, tracing
    2. Validation: Input/output schema validation
    3. Rate Limiting: Implement request throttling
    4. Caching: Redis or in-memory cache for responses
    5. Async Support: Non-blocking operations for scalability

    Feature Extensions

    1. Multi-Model Support: Switch between providers
    2. Fallback Models: Graceful degradation strategy
    3. Custom Tools: Domain-specific function calling
    4. Advanced Memory: Vector stores for long-term memory
    5. Evaluation: Automated testing and benchmarking

    Code Quality

    1. Testing: Unit tests, integration tests
    2. Documentation: API docs, usage examples
    3. Type Safety: Stricter type hints
    4. Configuration: Externalized config files

    Related Patterns

    • Pattern 130
    • Pattern 132

    Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


    Summary

    The Persona Consistency pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

    ✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

    🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

    📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


    File: 131_persona_consistency.py
    Total Lines: 787
    Pattern Category: AI Agent Design Pattern #131


    Generated from actual implementation code
    For educational and reference purposes