Tag: architecture

  • Agentic Architecture Pattern: Service Oriented

    
        """
    Pattern 100: Service-Oriented Pattern
    
    Agents expose functionality as services with well-defined interfaces.
    Services can be discovered, composed, and orchestrated.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class ServiceStatus(Enum):
        """Service status."""
        AVAILABLE = "available"
        BUSY = "busy"
        UNAVAILABLE = "unavailable"
        MAINTENANCE = "maintenance"
    
    
    @dataclass
    class ServiceContract:
        """Service contract defining interface."""
        service_name: str
        version: str
        description: str
        input_schema: Dict[str, str]
        output_schema: Dict[str, str]
        sla: Dict[str, Any] = field(default_factory=dict)  # Service Level Agreement
    
    
    @dataclass
    class ServiceCall:
        """Track service invocations."""
        service_name: str
        caller: str
        input_data: Any
        output_data: Any
        timestamp: datetime = field(default_factory=datetime.now)
        execution_time: float = 0.0
        success: bool = True
    
    
    class Service:
        """Service with defined contract."""
        
        def __init__(self, contract: ServiceContract, implementation: Callable):
            self.contract = contract
            self.implementation = implementation
            self.status = ServiceStatus.AVAILABLE
            self.call_count = 0
            self.total_execution_time = 0.0
        
        def invoke(self, input_data: Dict[str, Any], caller: str = "unknown") -> Dict[str, Any]:
            """Invoke the service."""
            if self.status != ServiceStatus.AVAILABLE:
                return {
                    "success": False,
                    "error": f"Service {self.contract.service_name} is {self.status.value}"
                }
            
            try:
                start = datetime.now()
                result = self.implementation(input_data)
                execution_time = (datetime.now() - start).total_seconds()
                
                self.call_count += 1
                self.total_execution_time += execution_time
                
                return {
                    "success": True,
                    "service": self.contract.service_name,
                    "version": self.contract.version,
                    "result": result,
                    "execution_time": execution_time
                }
            except Exception as e:
                return {
                    "success": False,
                    "error": str(e)
                }
        
        def get_metrics(self) -> Dict[str, Any]:
            """Get service metrics."""
            avg_time = self.total_execution_time / self.call_count if self.call_count > 0 else 0
            return {
                "service": self.contract.service_name,
                "status": self.status.value,
                "call_count": self.call_count,
                "average_execution_time": f"{avg_time:.3f}s"
            }
    
    
    class ServiceRegistry:
        """Registry for service discovery."""
        
        def __init__(self):
            self.services: Dict[str, Service] = {}
        
        def register(self, service: Service):
            """Register a service."""
            self.services[service.contract.service_name] = service
            print(f"Service registered: {service.contract.service_name} v{service.contract.version}")
        
        def unregister(self, service_name: str):
            """Unregister a service."""
            if service_name in self.services:
                del self.services[service_name]
                print(f"Service unregistered: {service_name}")
        
        def discover(self, query: str = "") -> List[str]:
            """Discover available services."""
            if not query:
                return list(self.services.keys())
            return [
                name for name in self.services.keys()
                if query.lower() in name.lower()
            ]
        
        def get_service(self, service_name: str) -> Optional[Service]:
            """Get a service by name."""
            return self.services.get(service_name)
    
    
    class ServiceOrientedPattern:
        """
        Service-Oriented Pattern - SOA for agents.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.llm = ChatOpenAI(model=model_name, temperature=0.5)
            self.registry = ServiceRegistry()
            self.call_history: List[ServiceCall] = []
        
        def create_llm_service(self, service_name: str, prompt_template: str) -> Service:
            """Create an LLM-backed service."""
            
            def implementation(input_data: Dict[str, Any]) -> str:
                prompt = ChatPromptTemplate.from_messages([
                    ("system", prompt_template),
                    ("human", "{input}")
                ])
                chain = prompt | self.llm
                response = chain.invoke({"input": str(input_data)})
                return str(response.content)
            
            contract = ServiceContract(
                service_name=service_name,
                version="1.0",
                description=f"LLM service: {service_name}",
                input_schema={"input": "any"},
                output_schema={"output": "string"}
            )
            
            return Service(contract, implementation)
        
        def call_service(self, service_name: str, input_data: Dict[str, Any], 
                        caller: str = "client") -> Dict[str, Any]:
            """Call a service."""
            service = self.registry.get_service(service_name)
            
            if not service:
                return {
                    "success": False,
                    "error": f"Service {service_name} not found"
                }
            
            result = service.invoke(input_data, caller)
            
            # Track call
            call = ServiceCall(
                service_name=service_name,
                caller=caller,
                input_data=input_data,
                output_data=result.get("result"),
                execution_time=result.get("execution_time", 0.0),
                success=result.get("success", False)
            )
            self.call_history.append(call)
            
            return result
        
        def compose_services(self, pipeline: List[tuple], input_data: Dict[str, Any]) -> Dict[str, Any]:
            """Compose multiple services in a pipeline."""
            results = []
            current_input = input_data
            
            for service_name, output_key in pipeline:
                result = self.call_service(service_name, current_input)
                
                if not result.get("success"):
                    return {
                        "success": False,
                        "error": f"Service {service_name} failed: {result.get('error')}"
                    }
                
                results.append({
                    "service": service_name,
                    "output": result.get("result")
                })
                
                # Pass output as input to next service
                current_input = {output_key: result.get("result")}
            
            return {
                "success": True,
                "pipeline": [s for s, _ in pipeline],
                "results": results
            }
        
        def run(self, service_name: str, input_data: Dict[str, Any]) -> Dict[str, Any]:
            """Execute service call."""
            result = self.call_service(service_name, input_data)
            
            return {
                "service": service_name,
                "input": input_data,
                "output": result,
                "available_services": self.registry.discover()
            }
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get system statistics."""
            return {
                "total_services": len(self.registry.services),
                "total_calls": len(self.call_history),
                "service_metrics": [
                    service.get_metrics()
                    for service in self.registry.services.values()
                ]
            }
    
    
    # Example usage
    if __name__ == "__main__":
        # Create pattern
        pattern = ServiceOrientedPattern()
        
        # Create and register services
        text_analyzer = pattern.create_llm_service(
            "text_analyzer",
            "Analyze the text and provide insights about sentiment, tone, and key topics."
        )
        pattern.registry.register(text_analyzer)
        
        summarizer = pattern.create_llm_service(
            "summarizer",
            "Summarize the following text in 2-3 sentences."
        )
        pattern.registry.register(summarizer)
        
        translator = pattern.create_llm_service(
            "translator",
            "Translate the text to Spanish."
        )
        pattern.registry.register(translator)
        
        print("=== Service-Oriented Pattern Demo ===\n")
        
        # Service discovery
        print("Available services:", pattern.registry.discover())
        print()
        
        # Call individual service
        print("1. Text Analysis Service:")
        result1 = pattern.run(
            "text_analyzer",
            {"text": "This product is amazing! I love using it every day."}
        )
        print(f"   Success: {result1['output']['success']}")
        print(f"   Result: {result1['output']['result'][:150]}...\n")
        
        # Call another service
        print("2. Summarization Service:")
        result2 = pattern.run(
            "summarizer",
            {"text": "Artificial intelligence is transforming industries worldwide. From healthcare to finance, AI systems are helping humans make better decisions. Machine learning algorithms can process vast amounts of data quickly."}
        )
        print(f"   Success: {result2['output']['success']}")
        print(f"   Result: {result2['output']['result']}\n")
        
        # Service composition
        print("3. Service Composition (Analyze → Summarize):")
        composition_result = pattern.compose_services(
            pipeline=[
                ("text_analyzer", "analysis"),
                ("summarizer", "summary")
            ],
            input_data={"text": "The future of AI is bright with many opportunities."}
        )
        print(f"   Success: {composition_result['success']}")
        print(f"   Pipeline: {' → '.join(composition_result['pipeline'])}")
        for step in composition_result['results']:
            print(f"   {step['service']}: {step['output'][:100]}...")
        
        # Show statistics
        print("\n\n=== Statistics ===")
        stats = pattern.get_statistics()
        print(f"Total services: {stats['total_services']}")
        print(f"Total calls: {stats['total_calls']}")
        print("\nService Metrics:")
        for metrics in stats['service_metrics']:
            print(f"  {metrics['service']}: {metrics['call_count']} calls, avg time: {metrics['average_execution_time']}")
    
        

    Agentic Architecture Pattern: Service Oriented

    Pattern 100: 100 Service Oriented – Line-by-Line Explanation

    Overview

    Pattern 100: Service-Oriented Pattern

    Agents expose functionality as services with well-defined interfaces. Services can be discovered, composed, and orchestrated.


    Code Structure Analysis

    File Information

    • Pattern Number: 100
    • Pattern Name: 100 Service Oriented
    • File Path: patterns\tool_resource\100_service_oriented.py
    • Total Lines: 307

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 100: Service-Oriented Pattern
    
    Agents expose functionality as services with well-defined interfaces.
    Services can be discovered, composed, and orchestrated.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 100 Service Oriented pattern.


    Imports Section

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

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


    Enumerations

    ServiceStatus (Line 16)

    class ServiceStatus(Enum):
        AVAILABLE
        BUSY
        UNAVAILABLE
        MAINTENANCE
    

    Purpose: Service status.

    Values: – AVAILABLE: Represents available – BUSY: Represents busy – UNAVAILABLE: Represents unavailable – MAINTENANCE: Represents maintenance


    Classes

    ServiceStatus (Line 16)

    Description: Service status.

    ServiceContract (Line 25)

    Description: Service contract defining interface.

    ServiceCall (Line 36)

    Description: Track service invocations.

    Service (Line 47)

    Description: Service with defined contract.

    Methods:

    __init__ (Line 50)
    def __init__(self, contract, implementation):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – contract: Parameter for contract – implementation: Parameter for implementation

    invoke (Line 57)
    def invoke(self, input_data, caller):
        """Invoke the service."""
    

    Purpose: Invoke the service.

    Parameters: – self: Instance reference – input_data: Parameter for input_data – caller: Parameter for caller

    get_metrics (Line 86)
    def get_metrics(self):
        """Get service metrics."""
    

    Purpose: Get service metrics.

    Parameters: – self: Instance reference

    ServiceRegistry (Line 97)

    Description: Registry for service discovery.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register (Line 103)
    def register(self, service):
        """Register a service."""
    

    Purpose: Register a service.

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

    unregister (Line 108)
    def unregister(self, service_name):
        """Unregister a service."""
    

    Purpose: Unregister a service.

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

    discover (Line 114)
    def discover(self, query):
        """Discover available services."""
    

    Purpose: Discover available services.

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

    get_service (Line 123)
    def get_service(self, service_name):
        """Get a service by name."""
    

    Purpose: Get a service by name.

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

    ServiceOrientedPattern (Line 128)

    Description: Service-Oriented Pattern – SOA for agents.

    Methods:

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

    Purpose: No method docstring.

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

    create_llm_service (Line 138)
    def create_llm_service(self, service_name, prompt_template):
        """Create an LLM-backed service."""
    

    Purpose: Create an LLM-backed service.

    Parameters: – self: Instance reference – service_name: Parameter for service_name – prompt_template: Parameter for prompt_template

    call_service (Line 160)
    def call_service(self, service_name, input_data, caller):
        """Call a service."""
    

    Purpose: Call a service.

    Parameters: – self: Instance reference – service_name: Parameter for service_name – input_data: Parameter for input_data – caller: Parameter for caller

    compose_services (Line 186)
    def compose_services(self, pipeline, input_data):
        """Compose multiple services in a pipeline."""
    

    Purpose: Compose multiple services in a pipeline.

    Parameters: – self: Instance reference – pipeline: Parameter for pipeline – input_data: Parameter for input_data

    run (Line 214)
    def run(self, service_name, input_data):
        """Execute service call."""
    

    Purpose: Execute service call.

    Parameters: – self: Instance reference – service_name: Parameter for service_name – input_data: Parameter for input_data

    get_statistics (Line 225)
    def get_statistics(self):
        """Get system statistics."""
    

    Purpose: Get system statistics.

    Parameters: – self: Instance reference


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = ServiceStatus(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Capability Based

    
        """
    Pattern 99: Capability-Based Pattern
    
    Agents declare and discover capabilities dynamically. Tasks are matched to agents
    based on their declared capabilities, enabling flexible task distribution.
    """
    
    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class CapabilityLevel(Enum):
        """Proficiency level for capabilities."""
        BASIC = 1
        INTERMEDIATE = 2
        ADVANCED = 3
        EXPERT = 4
    
    
    @dataclass
    class Capability:
        """Agent capability definition."""
        name: str
        description: str
        level: CapabilityLevel
        parameters: Dict[str, Any] = field(default_factory=dict)
        
        def __hash__(self):
            return hash(self.name)
        
        def __eq__(self, other):
            return self.name == other.name
    
    
    @dataclass
    class Task:
        """Task requiring specific capabilities."""
        id: str
        description: str
        required_capabilities: Set[str]
        priority: int = 1
        assigned_to: Optional[str] = None
    
    
    class CapableAgent:
        """Agent with declared capabilities."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.capabilities: Dict[str, Capability] = {}
            self.tasks_completed: int = 0
        
        def declare_capability(self, capability: Capability):
            """Declare a capability."""
            self.capabilities[capability.name] = capability
            print(f"{self.name} declared capability: {capability.name} ({capability.level.name})")
        
        def has_capability(self, capability_name: str) -> bool:
            """Check if agent has a capability."""
            return capability_name in self.capabilities
        
        def has_all_capabilities(self, capability_names: Set[str]) -> bool:
            """Check if agent has all required capabilities."""
            return all(self.has_capability(cap) for cap in capability_names)
        
        def get_capability_level(self, capability_name: str) -> Optional[CapabilityLevel]:
            """Get capability level."""
            if capability_name in self.capabilities:
                return self.capabilities[capability_name].level
            return None
        
        def execute_task(self, task: Task) -> str:
            """Execute a task using capabilities."""
            if not self.has_all_capabilities(task.required_capabilities):
                return f"Cannot execute - missing capabilities: {task.required_capabilities - set(self.capabilities.keys())}"
            
            # Use LLM to execute
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} with capabilities: {', '.join(self.capabilities.keys())}"),
                ("human", "Execute this task: {task}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"task": task.description})
            self.tasks_completed += 1
            
            return str(response.content)
    
    
    class CapabilityBasedPattern:
        """
        Capability-Based Pattern - Match tasks to agents by capabilities.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.model_name = model_name
            self.agents: Dict[str, CapableAgent] = {}
            self.tasks: List[Task] = []
            self.assignments: List[Dict[str, Any]] = []
        
        def register_agent(self, agent: CapableAgent):
            """Register an agent."""
            self.agents[agent.name] = agent
            print(f"Agent registered: {agent.name}")
        
        def find_capable_agents(self, required_capabilities: Set[str]) -> List[CapableAgent]:
            """Find all agents with required capabilities."""
            return [
                agent for agent in self.agents.values()
                if agent.has_all_capabilities(required_capabilities)
            ]
        
        def find_best_agent(self, task: Task) -> Optional[CapableAgent]:
            """Find best agent for task based on capability levels."""
            capable_agents = self.find_capable_agents(task.required_capabilities)
            
            if not capable_agents:
                return None
            
            # Score agents by capability levels
            def score_agent(agent: CapableAgent) -> float:
                return sum(
                    agent.get_capability_level(cap).value 
                    for cap in task.required_capabilities
                )
            
            return max(capable_agents, key=score_agent)
        
        def assign_task(self, task: Task) -> Dict[str, Any]:
            """Assign task to best agent."""
            agent = self.find_best_agent(task)
            
            if not agent:
                return {
                    "success": False,
                    "task_id": task.id,
                    "message": f"No agent found with capabilities: {task.required_capabilities}"
                }
            
            task.assigned_to = agent.name
            self.tasks.append(task)
            
            # Execute task
            result = agent.execute_task(task)
            
            assignment = {
                "task_id": task.id,
                "agent": agent.name,
                "capabilities_used": list(task.required_capabilities),
                "result": result,
                "timestamp": datetime.now()
            }
            self.assignments.append(assignment)
            
            return {
                "success": True,
                "task_id": task.id,
                "assigned_to": agent.name,
                "result": result
            }
        
        def get_capability_matrix(self) -> Dict[str, List[str]]:
            """Get matrix of agents and their capabilities."""
            return {
                agent_name: list(agent.capabilities.keys())
                for agent_name, agent in self.agents.items()
            }
        
        def run(self, task_description: str, 
                required_capabilities: Set[str]) -> Dict[str, Any]:
            """Execute capability-based task assignment."""
            task = Task(
                id=f"task_{len(self.tasks) + 1}",
                description=task_description,
                required_capabilities=required_capabilities
            )
            
            result = self.assign_task(task)
            
            return {
                "task": task_description,
                "required_capabilities": list(required_capabilities),
                "assignment": result,
                "capability_matrix": self.get_capability_matrix()
            }
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get pattern statistics."""
            return {
                "total_agents": len(self.agents),
                "total_tasks": len(self.tasks),
                "successful_assignments": sum(1 for a in self.assignments if a),
                "agent_performance": {
                    name: agent.tasks_completed
                    for name, agent in self.agents.items()
                }
            }
    
    
    # Example usage
    if __name__ == "__main__":
        # Create pattern
        pattern = CapabilityBasedPattern()
        
        # Create agents with capabilities
        agent1 = CapableAgent("DataScientist")
        agent1.declare_capability(Capability("data_analysis", "Analyze datasets", CapabilityLevel.EXPERT))
        agent1.declare_capability(Capability("visualization", "Create visualizations", CapabilityLevel.ADVANCED))
        agent1.declare_capability(Capability("python", "Python programming", CapabilityLevel.EXPERT))
        
        agent2 = CapableAgent("WebDeveloper")
        agent2.declare_capability(Capability("web_development", "Build web applications", CapabilityLevel.EXPERT))
        agent2.declare_capability(Capability("javascript", "JavaScript programming", CapabilityLevel.ADVANCED))
        agent2.declare_capability(Capability("api_design", "Design REST APIs", CapabilityLevel.INTERMEDIATE))
        
        agent3 = CapableAgent("DevOps")
        agent3.declare_capability(Capability("deployment", "Deploy applications", CapabilityLevel.EXPERT))
        agent3.declare_capability(Capability("monitoring", "Monitor systems", CapabilityLevel.ADVANCED))
        agent3.declare_capability(Capability("python", "Python programming", CapabilityLevel.INTERMEDIATE))
        
        # Register agents
        pattern.register_agent(agent1)
        pattern.register_agent(agent2)
        pattern.register_agent(agent3)
        
        print("\n=== Capability-Based Pattern Demo ===\n")
        
        # Task 1: Data analysis
        print("1. Task: Analyze customer data")
        result1 = pattern.run(
            "Analyze customer purchase patterns and create visualizations",
            {"data_analysis", "visualization"}
        )
        print(f"   Assigned to: {result1['assignment']['assigned_to']}")
        print(f"   Result: {result1['assignment']['result'][:100]}...\n")
        
        # Task 2: Web development
        print("2. Task: Build dashboard API")
        result2 = pattern.run(
            "Create REST API for dashboard application",
            {"web_development", "api_design"}
        )
        print(f"   Assigned to: {result2['assignment']['assigned_to']}")
        print(f"   Result: {result2['assignment']['result'][:100]}...\n")
        
        # Task 3: Multi-capability
        print("3. Task: Deploy monitoring solution")
        result3 = pattern.run(
            "Deploy and monitor the application",
            {"deployment", "monitoring"}
        )
        print(f"   Assigned to: {result3['assignment']['assigned_to']}")
        print(f"   Result: {result3['assignment']['result'][:100]}...\n")
        
        # Show capability matrix
        print("\n=== Capability Matrix ===")
        for agent_name, capabilities in pattern.get_capability_matrix().items():
            print(f"{agent_name}: {', '.join(capabilities)}")
        
        # Show statistics
        print("\n=== Statistics ===")
        stats = pattern.get_statistics()
        print(f"Total agents: {stats['total_agents']}")
        print(f"Total tasks: {stats['total_tasks']}")
        print(f"Agent performance: {stats['agent_performance']}")
    
        

    Agentic Architecture Pattern: Capability Based

    Pattern 99: 99 Capability Based – Line-by-Line Explanation

    Overview

    Pattern 99: Capability-Based Pattern

    Agents declare and discover capabilities dynamically. Tasks are matched to agents based on their declared capabilities, enabling flexible task distribution.


    Code Structure Analysis

    File Information

    • Pattern Number: 99
    • Pattern Name: 99 Capability Based
    • File Path: patterns\tool_resource\99_capability_based.py
    • Total Lines: 271

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 99: Capability-Based Pattern
    
    Agents declare and discover capabilities dynamically. Tasks are matched to agents
    based on their declared capabilities, enabling flexible task distribution.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 99 Capability Based pattern.


    Imports Section

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

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


    Enumerations

    CapabilityLevel (Line 16)

    class CapabilityLevel(Enum):
        BASIC
        INTERMEDIATE
        ADVANCED
        EXPERT
    

    Purpose: Proficiency level for capabilities.

    Values: – BASIC: Represents basic – INTERMEDIATE: Represents intermediate – ADVANCED: Represents advanced – EXPERT: Represents expert


    Classes

    CapabilityLevel (Line 16)

    Description: Proficiency level for capabilities.

    Capability (Line 25)

    Description: Agent capability definition.

    Methods:

    __hash__ (Line 32)
    def __hash__(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    __eq__ (Line 35)
    def __eq__(self, other):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    Task (Line 40)

    Description: Task requiring specific capabilities.

    CapableAgent (Line 49)

    Description: Agent with declared capabilities.

    Methods:

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

    Purpose: No method docstring.

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

    declare_capability (Line 58)
    def declare_capability(self, capability):
        """Declare a capability."""
    

    Purpose: Declare a capability.

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

    has_capability (Line 63)
    def has_capability(self, capability_name):
        """Check if agent has a capability."""
    

    Purpose: Check if agent has a capability.

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

    has_all_capabilities (Line 67)
    def has_all_capabilities(self, capability_names):
        """Check if agent has all required capabilities."""
    

    Purpose: Check if agent has all required capabilities.

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

    get_capability_level (Line 71)
    def get_capability_level(self, capability_name):
        """Get capability level."""
    

    Purpose: Get capability level.

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

    execute_task (Line 77)
    def execute_task(self, task):
        """Execute a task using capabilities."""
    

    Purpose: Execute a task using capabilities.

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

    CapabilityBasedPattern (Line 95)

    Description: Capability-Based Pattern – Match tasks to agents by capabilities.

    Methods:

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

    Purpose: No method docstring.

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

    register_agent (Line 106)
    def register_agent(self, agent):
        """Register an agent."""
    

    Purpose: Register an agent.

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

    find_capable_agents (Line 111)
    def find_capable_agents(self, required_capabilities):
        """Find all agents with required capabilities."""
    

    Purpose: Find all agents with required capabilities.

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

    find_best_agent (Line 118)
    def find_best_agent(self, task):
        """Find best agent for task based on capability levels."""
    

    Purpose: Find best agent for task based on capability levels.

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

    assign_task (Line 134)
    def assign_task(self, task):
        """Assign task to best agent."""
    

    Purpose: Assign task to best agent.

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

    get_capability_matrix (Line 167)
    def get_capability_matrix(self):
        """Get matrix of agents and their capabilities."""
    

    Purpose: Get matrix of agents and their capabilities.

    Parameters: – self: Instance reference

    run (Line 174)
    def run(self, task_description, required_capabilities):
        """Execute capability-based task assignment."""
    

    Purpose: Execute capability-based task assignment.

    Parameters: – self: Instance reference – task_description: Parameter for task_description – required_capabilities: Parameter for required_capabilities

    get_statistics (Line 192)
    def get_statistics(self):
        """Get pattern statistics."""
    

    Purpose: Get pattern statistics.

    Parameters: – self: Instance reference


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = CapabilityLevel(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Resource Manager

    
        """
    Pattern 98: Resource Manager Pattern
    
    Centralized management of computational resources (CPU, memory, API quotas, tokens)
    across agents with allocation, tracking, and optimization.
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class ResourceType(Enum):
        """Types of resources to manage."""
        CPU = "cpu"
        MEMORY = "memory"
        API_CALLS = "api_calls"
        TOKENS = "tokens"
        STORAGE = "storage"
    
    
    @dataclass
    class Resource:
        """Resource definition."""
        type: ResourceType
        total_capacity: float
        available: float
        unit: str = ""
        
        def allocate(self, amount: float) -> bool:
            """Allocate resource."""
            if self.available >= amount:
                self.available -= amount
                return True
            return False
        
        def release(self, amount: float):
            """Release resource."""
            self.available = min(self.available + amount, self.total_capacity)
        
        def utilization(self) -> float:
            """Get utilization percentage."""
            return ((self.total_capacity - self.available) / self.total_capacity) * 100
    
    
    @dataclass
    class ResourceAllocation:
        """Track resource allocation."""
        agent_id: str
        resource_type: ResourceType
        amount: float
        timestamp: datetime = field(default_factory=datetime.now)
        released: bool = False
    
    
    class ResourceManagerPattern:
        """
        Resource Manager Pattern - Centralized resource management.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.llm = ChatOpenAI(model=model_name, temperature=0.5)
            self.resources: Dict[ResourceType, Resource] = {}
            self.allocations: List[ResourceAllocation] = []
            self.agents: Dict[str, Dict[ResourceType, float]] = {}
        
        def add_resource(self, resource_type: ResourceType, capacity: float, unit: str = ""):
            """Add a resource pool."""
            self.resources[resource_type] = Resource(
                type=resource_type,
                total_capacity=capacity,
                available=capacity,
                unit=unit
            )
            print(f"Resource added: {resource_type.value} ({capacity} {unit})")
        
        def request_resources(self, agent_id: str, 
                             requests: Dict[ResourceType, float]) -> Dict[str, Any]:
            """Request resources for an agent."""
            # Check if all resources are available
            can_allocate = all(
                self.resources.get(r_type) and 
                self.resources[r_type].available >= amount
                for r_type, amount in requests.items()
            )
            
            if not can_allocate:
                return {
                    "success": False,
                    "message": "Insufficient resources",
                    "requested": requests,
                    "available": {
                        r_type: self.resources[r_type].available 
                        for r_type in requests.keys()
                        if r_type in self.resources
                    }
                }
            
            # Allocate all resources
            allocated = {}
            for r_type, amount in requests.items():
                if self.resources[r_type].allocate(amount):
                    allocation = ResourceAllocation(
                        agent_id=agent_id,
                        resource_type=r_type,
                        amount=amount
                    )
                    self.allocations.append(allocation)
                    allocated[r_type] = amount
                    
                    # Track per agent
                    if agent_id not in self.agents:
                        self.agents[agent_id] = {}
                    self.agents[agent_id][r_type] = self.agents[agent_id].get(r_type, 0) + amount
            
            return {
                "success": True,
                "message": "Resources allocated",
                "agent_id": agent_id,
                "allocated": allocated
            }
        
        def release_resources(self, agent_id: str, 
                             releases: Optional[Dict[ResourceType, float]] = None):
            """Release resources from an agent."""
            if releases is None:
                # Release all resources for agent
                releases = self.agents.get(agent_id, {})
            
            for r_type, amount in releases.items():
                if r_type in self.resources:
                    self.resources[r_type].release(amount)
                    
                    # Update agent tracking
                    if agent_id in self.agents and r_type in self.agents[agent_id]:
                        self.agents[agent_id][r_type] -= amount
                        if self.agents[agent_id][r_type]  Dict[str, Any]:
            """Get status of all resources."""
            return {
                r_type.value: {
                    "total": res.total_capacity,
                    "available": res.available,
                    "used": res.total_capacity - res.available,
                    "utilization": f"{res.utilization():.1f}%",
                    "unit": res.unit
                }
                for r_type, res in self.resources.items()
            }
        
        def get_agent_allocations(self, agent_id: str) -> Dict[str, Any]:
            """Get allocations for specific agent."""
            return {
                "agent_id": agent_id,
                "allocations": self.agents.get(agent_id, {}),
                "total_allocations": sum(self.agents.get(agent_id, {}).values())
            }
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute resource management scenario."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are a resource manager. Analyze the resource usage scenario."),
                ("human", "{scenario}\n\nCurrent status: {status}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({
                "scenario": scenario,
                "status": str(self.get_resource_status())
            })
            
            return {
                "scenario": scenario,
                "analysis": response.content,
                "resource_status": self.get_resource_status()
            }
    
    
    # Example usage
    if __name__ == "__main__":
        # Create resource manager
        manager = ResourceManagerPattern()
        
        # Add resources
        manager.add_resource(ResourceType.CPU, 100.0, "cores")
        manager.add_resource(ResourceType.MEMORY, 16384, "MB")
        manager.add_resource(ResourceType.API_CALLS, 1000, "calls/hour")
        manager.add_resource(ResourceType.TOKENS, 1000000, "tokens")
        
        print("\n=== Resource Manager Pattern Demo ===\n")
        
        # Initial status
        print("Initial Resource Status:")
        for r_type, info in manager.get_resource_status().items():
            print(f"  {r_type}: {info['available']}/{info['total']} {info['unit']} available ({info['utilization']} used)")
        
        # Agent 1 requests resources
        print("\n\n1. Agent 'DataProcessor' requesting resources:")
        result1 = manager.request_resources("DataProcessor", {
            ResourceType.CPU: 20.0,
            ResourceType.MEMORY: 4096,
            ResourceType.TOKENS: 100000
        })
        print(f"   Success: {result1['success']}")
        print(f"   Allocated: {result1['allocated']}")
        
        # Agent 2 requests resources
        print("\n2. Agent 'ModelTrainer' requesting resources:")
        result2 = manager.request_resources("ModelTrainer", {
            ResourceType.CPU: 50.0,
            ResourceType.MEMORY: 8192,
            ResourceType.API_CALLS: 500
        })
        print(f"   Success: {result2['success']}")
        print(f"   Allocated: {result2['allocated']}")
        
        # Show updated status
        print("\n\nUpdated Resource Status:")
        for r_type, info in manager.get_resource_status().items():
            print(f"  {r_type}: {info['available']}/{info['total']} {info['unit']} available ({info['utilization']} used)")
        
        # Show agent allocations
        print("\n\nAgent Allocations:")
        for agent_id in ["DataProcessor", "ModelTrainer"]:
            allocs = manager.get_agent_allocations(agent_id)
            print(f"  {agent_id}: {allocs['allocations']}")
        
        # Release resources
        print("\n\n3. Releasing resources from 'DataProcessor':")
        release_result = manager.release_resources("DataProcessor")
        print(f"   Success: {release_result['success']}")
        print(f"   Released: {release_result['released']}")
        
        # Final status
        print("\n\nFinal Resource Status:")
        for r_type, info in manager.get_resource_status().items():
            print(f"  {r_type}: {info['available']}/{info['total']} {info['unit']} available ({info['utilization']} used)")
    
        

    Agentic Architecture Pattern: Resource Manager

    Pattern 98: 98 Resource Manager – Line-by-Line Explanation

    Overview

    Pattern 98: Resource Manager Pattern

    Centralized management of computational resources (CPU, memory, API quotas, tokens) across agents with allocation, tracking, and optimization.


    Code Structure Analysis

    File Information

    • Pattern Number: 98
    • Pattern Name: 98 Resource Manager
    • File Path: patterns\tool_resource\98_resource_manager.py
    • Total Lines: 257

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 98: Resource Manager Pattern
    
    Centralized management of computational resources (CPU, memory, API quotas, tokens)
    across agents with allocation, tracking, and optimization.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 98 Resource Manager pattern.


    Imports Section

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

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


    Enumerations

    ResourceType (Line 16)

    class ResourceType(Enum):
        CPU
        MEMORY
        API_CALLS
        TOKENS
        STORAGE
    

    Purpose: Types of resources to manage.

    Values: – CPU: Represents cpu – MEMORY: Represents memory – API_CALLS: Represents api calls – TOKENS: Represents tokens – STORAGE: Represents storage


    Classes

    ResourceType (Line 16)

    Description: Types of resources to manage.

    Resource (Line 26)

    Description: Resource definition.

    Methods:

    allocate (Line 33)
    def allocate(self, amount):
        """Allocate resource."""
    

    Purpose: Allocate resource.

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

    release (Line 40)
    def release(self, amount):
        """Release resource."""
    

    Purpose: Release resource.

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

    utilization (Line 44)
    def utilization(self):
        """Get utilization percentage."""
    

    Purpose: Get utilization percentage.

    Parameters: – self: Instance reference

    ResourceAllocation (Line 50)

    Description: Track resource allocation.

    ResourceManagerPattern (Line 59)

    Description: Resource Manager Pattern – Centralized resource management.

    Methods:

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

    Purpose: No method docstring.

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

    add_resource (Line 70)
    def add_resource(self, resource_type, capacity, unit):
        """Add a resource pool."""
    

    Purpose: Add a resource pool.

    Parameters: – self: Instance reference – resource_type: Parameter for resource_type – capacity: Parameter for capacity – unit: Parameter for unit

    request_resources (Line 80)
    def request_resources(self, agent_id, requests):
        """Request resources for an agent."""
    

    Purpose: Request resources for an agent.

    Parameters: – self: Instance reference – agent_id: Parameter for agent_id – requests: Parameter for requests

    release_resources (Line 126)
    def release_resources(self, agent_id, releases):
        """Release resources from an agent."""
    

    Purpose: Release resources from an agent.

    Parameters: – self: Instance reference – agent_id: Parameter for agent_id – releases: Parameter for releases

    get_resource_status (Line 157)
    def get_resource_status(self):
        """Get status of all resources."""
    

    Purpose: Get status of all resources.

    Parameters: – self: Instance reference

    get_agent_allocations (Line 170)
    def get_agent_allocations(self, agent_id):
        """Get allocations for specific agent."""
    

    Purpose: Get allocations for specific agent.

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

    run (Line 178)
    def run(self, scenario):
        """Execute resource management scenario."""
    

    Purpose: Execute resource management scenario.

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


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = ResourceType(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Adapter

    
        """
    Pattern 97: Adapter Pattern
    
    Adapt incompatible interfaces between agents or systems, allowing them to work together.
    Translates data formats, protocols, and communication patterns.
    """
    
    from typing import Dict, Any, List, Optional, Protocol
    from dataclasses import dataclass, field
    from datetime import datetime
    from abc import ABC, abstractmethod
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    import json
    
    
    class AgentInterface(ABC):
        """Standard agent interface."""
        
        @abstractmethod
        def process(self, data: Dict[str, Any]) -> Dict[str, Any]:
            """Process data in standard format."""
            pass
    
    
    class LegacySystemA:
        """Legacy system with incompatible interface."""
        
        def execute_command(self, cmd: str, params: List[str]) -> str:
            """Legacy method with string-based interface."""
            return f"LegacyA executed: {cmd} with {params}"
    
    
    class LegacySystemB:
        """Another legacy system with different interface."""
        
        def run_task(self, task_id: int, config: str) -> tuple:
            """Legacy method returning tuple."""
            return (task_id, f"Task {task_id} completed", config)
    
    
    @dataclass
    class AdaptedRequest:
        """Standardized request format."""
        action: str
        parameters: Dict[str, Any]
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class AdaptedResponse:
        """Standardized response format."""
        success: bool
        data: Any
        message: str
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class LegacySystemAAdapter(AgentInterface):
        """Adapter for LegacySystemA."""
        
        def __init__(self):
            self.system = LegacySystemA()
        
        def process(self, data: Dict[str, Any]) -> Dict[str, Any]:
            """Adapt standard format to LegacySystemA format."""
            # Convert standard format to legacy format
            cmd = data.get("action", "default")
            params = data.get("parameters", {})
            params_list = [f"{k}={v}" for k, v in params.items()]
            
            # Call legacy method
            result = self.system.execute_command(cmd, params_list)
            
            # Convert result back to standard format
            return {
                "success": True,
                "data": result,
                "message": "LegacySystemA adapted successfully"
            }
    
    
    class LegacySystemBAdapter(AgentInterface):
        """Adapter for LegacySystemB."""
        
        def __init__(self):
            self.system = LegacySystemB()
        
        def process(self, data: Dict[str, Any]) -> Dict[str, Any]:
            """Adapt standard format to LegacySystemB format."""
            # Convert standard format to legacy format
            task_id = hash(data.get("action", "")) % 10000
            config = json.dumps(data.get("parameters", {}))
            
            # Call legacy method
            result_tuple = self.system.run_task(task_id, config)
            
            # Convert tuple result back to standard format
            return {
                "success": True,
                "data": {
                    "task_id": result_tuple[0],
                    "message": result_tuple[1],
                    "config": result_tuple[2]
                },
                "message": "LegacySystemB adapted successfully"
            }
    
    
    class ModernAgent(AgentInterface):
        """Modern agent with standard interface."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.5)
        
        def process(self, data: Dict[str, Any]) -> Dict[str, Any]:
            """Process with LLM."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. Process the request and provide a response."),
                ("human", "Action: {action}\nParameters: {parameters}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({
                "action": data.get("action", ""),
                "parameters": str(data.get("parameters", {}))
            })
            
            return {
                "success": True,
                "data": response.content,
                "message": f"Processed by {self.name}"
            }
    
    
    class AdapterPattern:
        """
        Adapter Pattern - Manage adapters for different systems.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.model_name = model_name
            self.adapters: Dict[str, AgentInterface] = {}
            self.call_history: List[Dict[str, Any]] = []
        
        def register_adapter(self, name: str, adapter: AgentInterface):
            """Register an adapter."""
            self.adapters[name] = adapter
            print(f"Adapter registered: {name}")
        
        def process_request(self, adapter_name: str, request: AdaptedRequest) -> AdaptedResponse:
            """Process request through specified adapter."""
            if adapter_name not in self.adapters:
                return AdaptedResponse(
                    success=False,
                    data=None,
                    message=f"Adapter {adapter_name} not found"
                )
            
            adapter = self.adapters[adapter_name]
            
            # Convert request to dict
            request_data = {
                "action": request.action,
                "parameters": request.parameters
            }
            
            # Process through adapter
            result = adapter.process(request_data)
            
            # Track call
            self.call_history.append({
                "adapter": adapter_name,
                "request": request_data,
                "response": result,
                "timestamp": datetime.now()
            })
            
            # Convert to standard response
            return AdaptedResponse(
                success=result.get("success", False),
                data=result.get("data"),
                message=result.get("message", "")
            )
        
        def run(self, adapter_name: str, action: str, 
                parameters: Dict[str, Any]) -> Dict[str, Any]:
            """Execute through adapter."""
            request = AdaptedRequest(action=action, parameters=parameters)
            response = self.process_request(adapter_name, request)
            
            return {
                "adapter": adapter_name,
                "request": {
                    "action": action,
                    "parameters": parameters
                },
                "response": {
                    "success": response.success,
                    "data": response.data,
                    "message": response.message
                }
            }
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get adapter usage statistics."""
            return {
                "total_adapters": len(self.adapters),
                "total_calls": len(self.call_history),
                "calls_by_adapter": {
                    name: sum(1 for call in self.call_history if call["adapter"] == name)
                    for name in self.adapters.keys()
                }
            }
    
    
    # Example usage
    if __name__ == "__main__":
        # Create pattern
        pattern = AdapterPattern()
        
        # Register adapters
        pattern.register_adapter("legacy_a", LegacySystemAAdapter())
        pattern.register_adapter("legacy_b", LegacySystemBAdapter())
        pattern.register_adapter("modern", ModernAgent("ModernProcessor"))
        
        print("\n=== Adapter Pattern Demo ===\n")
        
        # Test LegacySystemA adapter
        print("1. Testing LegacySystemA Adapter:")
        result1 = pattern.run(
            "legacy_a",
            action="deploy",
            parameters={"env": "production", "version": "2.0"}
        )
        print(f"   Action: {result1['request']['action']}")
        print(f"   Response: {result1['response']['data']}")
        print(f"   Message: {result1['response']['message']}\n")
        
        # Test LegacySystemB adapter
        print("2. Testing LegacySystemB Adapter:")
        result2 = pattern.run(
            "legacy_b",
            action="backup",
            parameters={"database": "users", "incremental": True}
        )
        print(f"   Action: {result2['request']['action']}")
        print(f"   Response Data: {result2['response']['data']}")
        print(f"   Message: {result2['response']['message']}\n")
        
        # Test Modern agent
        print("3. Testing Modern Agent:")
        result3 = pattern.run(
            "modern",
            action="analyze",
            parameters={"dataset": "sales_q4", "metric": "revenue"}
        )
        print(f"   Action: {result3['request']['action']}")
        print(f"   Response: {result3['response']['data'][:100]}...")
        print(f"   Message: {result3['response']['message']}\n")
        
        # Show statistics
        print("=== Statistics ===")
        stats = pattern.get_statistics()
        print(f"Total adapters: {stats['total_adapters']}")
        print(f"Total calls: {stats['total_calls']}")
        print(f"Calls by adapter: {stats['calls_by_adapter']}")
    
        

    Agentic Architecture Pattern: Adapter

    Pattern 97: 97 Adapter – Line-by-Line Explanation

    Overview

    Pattern 97: Adapter Pattern

    Adapt incompatible interfaces between agents or systems, allowing them to work together. Translates data formats, protocols, and communication patterns.


    Code Structure Analysis

    File Information

    • Pattern Number: 97
    • Pattern Name: 97 Adapter
    • File Path: patterns\tool_resource\97_adapter.py
    • Total Lines: 269

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 97: Adapter Pattern
    
    Adapt incompatible interfaces between agents or systems, allowing them to work together.
    Translates data formats, protocols, and communication patterns.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 97 Adapter pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Protocol
    from dataclasses import dataclass, field
    from datetime import datetime
    from abc import ABC, abstractmethod
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    import json  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional, Protocol: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from datetime import datetime: Date and time utilities – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration – import json: JSON parsing and serialization


    Classes

    AgentInterface (Line 17)

    Description: Standard agent interface.

    Methods:

    process (Line 21)
    def process(self, data):
        """Process data in standard format."""
    

    Purpose: Process data in standard format.

    Parameters: – self: Instance reference – data: Input data to process

    LegacySystemA (Line 26)

    Description: Legacy system with incompatible interface.

    Methods:

    execute_command (Line 29)
    def execute_command(self, cmd, params):
        """Legacy method with string-based interface."""
    

    Purpose: Legacy method with string-based interface.

    Parameters: – self: Instance reference – cmd: Parameter for cmd – params: Parameter for params

    LegacySystemB (Line 34)

    Description: Another legacy system with different interface.

    Methods:

    run_task (Line 37)
    def run_task(self, task_id, config):
        """Legacy method returning tuple."""
    

    Purpose: Legacy method returning tuple.

    Parameters: – self: Instance reference – task_id: Parameter for task_id – config: Configuration settings

    AdaptedRequest (Line 43)

    Description: Standardized request format.

    AdaptedResponse (Line 51)

    Description: Standardized response format.

    LegacySystemAAdapter (Line 59)

    Description: Adapter for LegacySystemA.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    process (Line 65)
    def process(self, data):
        """Adapt standard format to LegacySystemA format."""
    

    Purpose: Adapt standard format to LegacySystemA format.

    Parameters: – self: Instance reference – data: Input data to process

    LegacySystemBAdapter (Line 83)

    Description: Adapter for LegacySystemB.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    process (Line 89)
    def process(self, data):
        """Adapt standard format to LegacySystemB format."""
    

    Purpose: Adapt standard format to LegacySystemB format.

    Parameters: – self: Instance reference – data: Input data to process

    ModernAgent (Line 110)

    Description: Modern agent with standard interface.

    Methods:

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

    Purpose: No method docstring.

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

    process (Line 117)
    def process(self, data):
        """Process with LLM."""
    

    Purpose: Process with LLM.

    Parameters: – self: Instance reference – data: Input data to process

    AdapterPattern (Line 137)

    Description: Adapter Pattern – Manage adapters for different systems.

    Methods:

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

    Purpose: No method docstring.

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

    register_adapter (Line 147)
    def register_adapter(self, name, adapter):
        """Register an adapter."""
    

    Purpose: Register an adapter.

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

    process_request (Line 152)
    def process_request(self, adapter_name, request):
        """Process request through specified adapter."""
    

    Purpose: Process request through specified adapter.

    Parameters: – self: Instance reference – adapter_name: Parameter for adapter_name – request: Parameter for request

    run (Line 187)
    def run(self, adapter_name, action, parameters):
        """Execute through adapter."""
    

    Purpose: Execute through adapter.

    Parameters: – self: Instance reference – adapter_name: Parameter for adapter_name – action: Parameter for action – parameters: Parameter for parameters

    get_statistics (Line 206)
    def get_statistics(self):
        """Get adapter usage statistics."""
    

    Purpose: Get adapter usage statistics.

    Parameters: – self: Instance reference


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = AgentInterface(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Extension

    
        """
    Pattern 96: Extension Pattern
    
    Extend agent behavior by adding new capabilities without modifying existing code.
    Extensions inherit from base agent and add specific features.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from abc import ABC, abstractmethod
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class BaseAgent(ABC):
        """Base agent that can be extended."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
        
        @abstractmethod
        def core_capability(self, input_data: str) -> str:
            """Core capability of the agent."""
            pass
    
    
    @dataclass
    class Extension:
        """Extension that adds capabilities."""
        name: str
        capability: Callable
        description: str
        priority: int = 0
        enabled: bool = True
        call_count: int = 0
    
    
    class ExtensibleAgent(BaseAgent):
        """Agent that supports extensions."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            super().__init__(name, model_name)
            self.extensions: Dict[str, Extension] = {}
        
        def core_capability(self, input_data: str) -> str:
            """Core capability - basic text processing."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, a base AI agent."),
                ("human", "{input}")
            ])
            chain = prompt | self.llm
            response = chain.invoke({"input": input_data})
            return str(response.content)
        
        def add_extension(self, name: str, capability: Callable, 
                         description: str, priority: int = 0):
            """Add an extension."""
            extension = Extension(
                name=name,
                capability=capability,
                description=description,
                priority=priority
            )
            self.extensions[name] = extension
            print(f"Extension added: {name} (priority: {priority})")
        
        def remove_extension(self, name: str):
            """Remove an extension."""
            if name in self.extensions:
                del self.extensions[name]
                print(f"Extension removed: {name}")
        
        def enable_extension(self, name: str):
            """Enable an extension."""
            if name in self.extensions:
                self.extensions[name].enabled = True
        
        def disable_extension(self, name: str):
            """Disable an extension."""
            if name in self.extensions:
                self.extensions[name].enabled = False
        
        def execute_with_extensions(self, input_data: str) -> Dict[str, Any]:
            """Execute with all enabled extensions."""
            results = {
                "core_result": self.core_capability(input_data),
                "extension_results": {}
            }
            
            # Sort extensions by priority (higher priority first)
            sorted_extensions = sorted(
                self.extensions.values(),
                key=lambda e: e.priority,
                reverse=True
            )
            
            # Execute enabled extensions
            for ext in sorted_extensions:
                if ext.enabled:
                    try:
                        result = ext.capability(input_data)
                        results["extension_results"][ext.name] = result
                        ext.call_count += 1
                    except Exception as e:
                        results["extension_results"][ext.name] = f"Error: {str(e)}"
            
            return results
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get extension statistics."""
            return {
                "total_extensions": len(self.extensions),
                "enabled_extensions": sum(1 for e in self.extensions.values() if e.enabled),
                "extension_calls": {
                    name: ext.call_count
                    for name, ext in self.extensions.items()
                }
            }
    
    
    class ExtensionPattern:
        """
        Extension Pattern - Manage extensible agents.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.model_name = model_name
            self.agents: Dict[str, ExtensibleAgent] = {}
        
        def create_agent(self, name: str) -> ExtensibleAgent:
            """Create a new extensible agent."""
            agent = ExtensibleAgent(name, self.model_name)
            self.agents[name] = agent
            return agent
        
        def run(self, agent_name: str, input_data: str) -> Dict[str, Any]:
            """Run agent with extensions."""
            if agent_name not in self.agents:
                return {"error": f"Agent {agent_name} not found"}
            
            agent = self.agents[agent_name]
            result = agent.execute_with_extensions(input_data)
            
            return {
                "agent": agent_name,
                "input": input_data,
                "results": result,
                "statistics": agent.get_statistics()
            }
    
    
    # Example usage
    if __name__ == "__main__":
        # Create pattern
        pattern = ExtensionPattern()
        
        # Create agent
        agent = pattern.create_agent("SmartAssistant")
        
        # Add extensions
        agent.add_extension(
            name="sentiment_analyzer",
            capability=lambda text: "positive" if "good" in text.lower() or "great" in text.lower() else "neutral",
            description="Analyzes sentiment of text",
            priority=10
        )
        
        agent.add_extension(
            name="word_counter",
            capability=lambda text: f"{len(text.split())} words",
            description="Counts words in text",
            priority=5
        )
        
        agent.add_extension(
            name="text_summarizer",
            capability=lambda text: text[:50] + "..." if len(text) > 50 else text,
            description="Summarizes long text",
            priority=3
        )
        
        # Test
        print("=== Extension Pattern Demo ===\n")
        
        # Run with extensions
        result = pattern.run("SmartAssistant", "This is a great day to learn about AI extensions!")
        
        print(f"Agent: {result['agent']}")
        print(f"\nInput: {result['input']}")
        print(f"\nCore Result: {result['results']['core_result'][:100]}...")
        print(f"\nExtension Results:")
        for ext_name, ext_result in result['results']['extension_results'].items():
            print(f"  - {ext_name}: {ext_result}")
        
        print(f"\nStatistics:")
        stats = result['statistics']
        print(f"  Total extensions: {stats['total_extensions']}")
        print(f"  Enabled extensions: {stats['enabled_extensions']}")
        print(f"  Extension calls: {stats['extension_calls']}")
        
        # Test with disabled extension
        print("\n\n=== Disabling sentiment_analyzer ===")
        agent.disable_extension("sentiment_analyzer")
        
        result2 = pattern.run("SmartAssistant", "Another test message")
        print(f"\nExtension Results:")
        for ext_name, ext_result in result2['results']['extension_results'].items():
            print(f"  - {ext_name}: {ext_result}")
    
        

    Agentic Architecture Pattern: Extension

    Pattern 96: 96 Extension – Line-by-Line Explanation

    Overview

    Pattern 96: Extension Pattern

    Extend agent behavior by adding new capabilities without modifying existing code. Extensions inherit from base agent and add specific features.


    Code Structure Analysis

    File Information

    • Pattern Number: 96
    • Pattern Name: 96 Extension
    • File Path: patterns\tool_resource\96_extension.py
    • Total Lines: 211

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 96: Extension Pattern
    
    Extend agent behavior by adding new capabilities without modifying existing code.
    Extensions inherit from base agent and add specific features.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 96 Extension pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from abc import ABC, abstractmethod
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI  # First 20 imports shown
    

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


    Classes

    BaseAgent (Line 16)

    Description: Base agent that can be extended.

    Methods:

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

    Purpose: No method docstring.

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

    core_capability (Line 24)
    def core_capability(self, input_data):
        """Core capability of the agent."""
    

    Purpose: Core capability of the agent.

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

    Extension (Line 30)

    Description: Extension that adds capabilities.

    ExtensibleAgent (Line 40)

    Description: Agent that supports extensions.

    Methods:

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

    Purpose: No method docstring.

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

    core_capability (Line 47)
    def core_capability(self, input_data):
        """Core capability - basic text processing."""
    

    Purpose: Core capability – basic text processing.

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

    add_extension (Line 57)
    def add_extension(self, name, capability, description, priority):
        """Add an extension."""
    

    Purpose: Add an extension.

    Parameters: – self: Instance reference – name: Identifier or label – capability: Parameter for capability – description: Parameter for description – priority: Parameter for priority

    remove_extension (Line 69)
    def remove_extension(self, name):
        """Remove an extension."""
    

    Purpose: Remove an extension.

    Parameters: – self: Instance reference – name: Identifier or label

    enable_extension (Line 75)
    def enable_extension(self, name):
        """Enable an extension."""
    

    Purpose: Enable an extension.

    Parameters: – self: Instance reference – name: Identifier or label

    disable_extension (Line 80)
    def disable_extension(self, name):
        """Disable an extension."""
    

    Purpose: Disable an extension.

    Parameters: – self: Instance reference – name: Identifier or label

    execute_with_extensions (Line 85)
    def execute_with_extensions(self, input_data):
        """Execute with all enabled extensions."""
    

    Purpose: Execute with all enabled extensions.

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

    get_statistics (Line 111)
    def get_statistics(self):
        """Get extension statistics."""
    

    Purpose: Get extension statistics.

    Parameters: – self: Instance reference

    ExtensionPattern (Line 123)

    Description: Extension Pattern – Manage extensible agents.

    Methods:

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

    Purpose: No method docstring.

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

    create_agent (Line 132)
    def create_agent(self, name):
        """Create a new extensible agent."""
    

    Purpose: Create a new extensible agent.

    Parameters: – self: Instance reference – name: Identifier or label

    run (Line 138)
    def run(self, agent_name, input_data):
        """Run agent with extensions."""
    

    Purpose: Run agent with extensions.

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


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = BaseAgent(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Plugin

    
        """
    Pattern 95: Plugin Pattern
    
    Dynamically extend agent capabilities by loading plugins at runtime.
    Plugins implement a common interface and can be added/removed without
    modifying the core agent.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from abc import ABC, abstractmethod
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class Plugin(ABC):
        """Base class for plugins."""
        
        @abstractmethod
        def get_name(self) -> str:
            """Return plugin name."""
            pass
        
        @abstractmethod
        def get_version(self) -> str:
            """Return plugin version."""
            pass
        
        @abstractmethod
        def execute(self, context: Dict[str, Any], input_data: Any) -> Any:
            """Execute plugin functionality."""
            pass
        
        def initialize(self):
            """Optional initialization."""
            pass
        
        def cleanup(self):
            """Optional cleanup."""
            pass
    
    
    @dataclass
    class PluginMetadata:
        """Metadata about an installed plugin."""
        name: str
        version: str
        enabled: bool = True
        load_time: datetime = field(default_factory=datetime.now)
        execution_count: int = 0
    
    
    class PluginPattern:
        """
        Plugin Pattern - Extensible agent through plugins.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.llm = ChatOpenAI(model=model_name, temperature=0.5)
            self.plugins: Dict[str, Plugin] = {}
            self.metadata: Dict[str, PluginMetadata] = {}
        
        def register_plugin(self, plugin: Plugin):
            """Register a plugin."""
            plugin.initialize()
            name = plugin.get_name()
            self.plugins[name] = plugin
            self.metadata[name] = PluginMetadata(
                name=name,
                version=plugin.get_version()
            )
            print(f"Plugin registered: {name} v{plugin.get_version()}")
        
        def unregister_plugin(self, plugin_name: str):
            """Unregister a plugin."""
            if plugin_name in self.plugins:
                self.plugins[plugin_name].cleanup()
                del self.plugins[plugin_name]
                del self.metadata[plugin_name]
                print(f"Plugin unregistered: {plugin_name}")
        
        def enable_plugin(self, plugin_name: str):
            """Enable a plugin."""
            if plugin_name in self.metadata:
                self.metadata[plugin_name].enabled = True
        
        def disable_plugin(self, plugin_name: str):
            """Disable a plugin."""
            if plugin_name in self.metadata:
                self.metadata[plugin_name].enabled = False
        
        def execute_plugin(self, plugin_name: str, input_data: Any, context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
            """Execute a specific plugin."""
            if plugin_name not in self.plugins:
                return {"error": f"Plugin {plugin_name} not found"}
            
            if not self.metadata[plugin_name].enabled:
                return {"error": f"Plugin {plugin_name} is disabled"}
            
            context = context or {}
            
            try:
                result = self.plugins[plugin_name].execute(context, input_data)
                self.metadata[plugin_name].execution_count += 1
                return {"success": True, "result": result}
            except Exception as e:
                return {"success": False, "error": str(e)}
        
        def run(self, task: str) -> Dict[str, Any]:
            """Run task using available plugins."""
            # Use LLM to determine which plugins to use
            plugin_list = [f"{name} ({meta.version})" for name, meta in self.metadata.items() if meta.enabled]
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"Available plugins: {', '.join(plugin_list)}. Determine which plugins to use for the task."),
                ("human", "{task}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"task": task})
            
            return {
                "task": task,
                "available_plugins": len(plugin_list),
                "recommendation": response.content
            }
        
        def list_plugins(self) -> List[Dict[str, Any]]:
            """List all registered plugins."""
            return [
                {
                    "name": meta.name,
                    "version": meta.version,
                    "enabled": meta.enabled,
                    "executions": meta.execution_count
                }
                for meta in self.metadata.values()
            ]
    
    
    # Example plugins
    class TextAnalysisPlugin(Plugin):
        """Plugin for text analysis."""
        
        def get_name(self) -> str:
            return "TextAnalysis"
        
        def get_version(self) -> str:
            return "1.0.0"
        
        def execute(self, context: Dict[str, Any], input_data: Any) -> Any:
            text = str(input_data)
            return {
                "length": len(text),
                "words": len(text.split()),
                "uppercase": text.upper(),
                "lowercase": text.lower()
            }
    
    
    class MathPlugin(Plugin):
        """Plugin for math operations."""
        
        def get_name(self) -> str:
            return "Math"
        
        def get_version(self) -> str:
            return "1.0.0"
        
        def execute(self, context: Dict[str, Any], input_data: Any) -> Any:
            if isinstance(input_data, (list, tuple)):
                return {
                    "sum": sum(input_data),
                    "average": sum(input_data) / len(input_data) if input_data else 0,
                    "min": min(input_data) if input_data else None,
                    "max": max(input_data) if input_data else None
                }
            return {"error": "Input must be a list or tuple"}
    
    
    class LoggerPlugin(Plugin):
        """Plugin for logging."""
        
        def __init__(self):
            self.logs = []
        
        def get_name(self) -> str:
            return "Logger"
        
        def get_version(self) -> str:
            return "1.0.0"
        
        def execute(self, context: Dict[str, Any], input_data: Any) -> Any:
            log_entry = f"[{datetime.now()}] {input_data}"
            self.logs.append(log_entry)
            return {"logged": True, "entry": log_entry}
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Plugin Pattern Demo ===\n")
        
        pattern = PluginPattern()
        
        # Register plugins
        pattern.register_plugin(TextAnalysisPlugin())
        pattern.register_plugin(MathPlugin())
        pattern.register_plugin(LoggerPlugin())
        
        print(f"\nRegistered plugins: {len(pattern.list_plugins())}\n")
        
        # Execute plugins
        result1 = pattern.execute_plugin("TextAnalysis", "Hello World!")
        print(f"TextAnalysis result: {result1['result']}\n")
        
        result2 = pattern.execute_plugin("Math", [1, 2, 3, 4, 5])
        print(f"Math result: {result2['result']}\n")
        
        result3 = pattern.execute_plugin("Logger", "Task completed successfully")
        print(f"Logger result: {result3['result']}\n")
        
        # List all plugins
        print("=== Plugin Status ===")
        for plugin in pattern.list_plugins():
            print(f"- {plugin['name']} v{plugin['version']}: "
                  f"{'enabled' if plugin['enabled'] else 'disabled'}, "
                  f"{plugin['executions']} executions")
        
        # Disable and test
        print("\n=== Testing Plugin Disable ===")
        pattern.disable_plugin("Math")
        result4 = pattern.execute_plugin("Math", [1, 2, 3])
        print(f"Attempt to use disabled plugin: {result4}")
    
        

    Agentic Architecture Pattern: Plugin

    Pattern 95: 95 Plugin – Line-by-Line Explanation

    Overview

    Pattern 95: Plugin Pattern

    Dynamically extend agent capabilities by loading plugins at runtime. Plugins implement a common interface and can be added/removed without modifying the core agent.


    Code Structure Analysis

    File Information

    • Pattern Number: 95
    • Pattern Name: 95 Plugin
    • File Path: patterns\tool_resource\95_plugin.py
    • Total Lines: 235

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 95: Plugin Pattern
    
    Dynamically extend agent capabilities by loading plugins at runtime.
    Plugins implement a common interface and can be added/removed without
    modifying the core agent.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 95 Plugin pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from abc import ABC, abstractmethod
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI  # First 20 imports shown
    

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


    Classes

    Plugin (Line 17)

    Description: Base class for plugins.

    Methods:

    get_name (Line 21)
    def get_name(self):
        """Return plugin name."""
    

    Purpose: Return plugin name.

    Parameters: – self: Instance reference

    get_version (Line 26)
    def get_version(self):
        """Return plugin version."""
    

    Purpose: Return plugin version.

    Parameters: – self: Instance reference

    execute (Line 31)
    def execute(self, context, input_data):
        """Execute plugin functionality."""
    

    Purpose: Execute plugin functionality.

    Parameters: – self: Instance reference – context: Parameter for context – input_data: Parameter for input_data

    initialize (Line 35)
    def initialize(self):
        """Optional initialization."""
    

    Purpose: Optional initialization.

    Parameters: – self: Instance reference

    cleanup (Line 39)
    def cleanup(self):
        """Optional cleanup."""
    

    Purpose: Optional cleanup.

    Parameters: – self: Instance reference

    PluginMetadata (Line 45)

    Description: Metadata about an installed plugin.

    PluginPattern (Line 54)

    Description: Plugin Pattern – Extensible agent through plugins.

    Methods:

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

    Purpose: No method docstring.

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

    register_plugin (Line 64)
    def register_plugin(self, plugin):
        """Register a plugin."""
    

    Purpose: Register a plugin.

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

    unregister_plugin (Line 75)
    def unregister_plugin(self, plugin_name):
        """Unregister a plugin."""
    

    Purpose: Unregister a plugin.

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

    enable_plugin (Line 83)
    def enable_plugin(self, plugin_name):
        """Enable a plugin."""
    

    Purpose: Enable a plugin.

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

    disable_plugin (Line 88)
    def disable_plugin(self, plugin_name):
        """Disable a plugin."""
    

    Purpose: Disable a plugin.

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

    execute_plugin (Line 93)
    def execute_plugin(self, plugin_name, input_data, context):
        """Execute a specific plugin."""
    

    Purpose: Execute a specific plugin.

    Parameters: – self: Instance reference – plugin_name: Parameter for plugin_name – input_data: Parameter for input_data – context: Parameter for context

    run (Line 110)
    def run(self, task):
        """Run task using available plugins."""
    

    Purpose: Run task using available plugins.

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

    list_plugins (Line 129)
    def list_plugins(self):
        """List all registered plugins."""
    

    Purpose: List all registered plugins.

    Parameters: – self: Instance reference

    TextAnalysisPlugin (Line 143)

    Description: Plugin for text analysis.

    Methods:

    get_name (Line 146)
    def get_name(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    get_version (Line 149)
    def get_version(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    execute (Line 152)
    def execute(self, context, input_data):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – context: Parameter for context – input_data: Parameter for input_data

    MathPlugin (Line 162)

    Description: Plugin for math operations.

    Methods:

    get_name (Line 165)
    def get_name(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    get_version (Line 168)
    def get_version(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    execute (Line 171)
    def execute(self, context, input_data):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – context: Parameter for context – input_data: Parameter for input_data

    LoggerPlugin (Line 182)

    Description: Plugin for logging.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    get_name (Line 188)
    def get_name(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    get_version (Line 191)
    def get_version(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    execute (Line 194)
    def execute(self, context, input_data):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – context: Parameter for context – input_data: Parameter for input_data


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = Plugin(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Api Integration

    
        """
    Pattern 94: API Integration Pattern
    
    Agents that integrate with external APIs (REST, GraphQL, etc.) to fetch data,
    trigger actions, or interact with external systems.
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    import json
    
    
    class HTTPMethod(Enum):
        """HTTP methods."""
        GET = "GET"
        POST = "POST"
        PUT = "PUT"
        DELETE = "DELETE"
        PATCH = "PATCH"
    
    
    @dataclass
    class APIEndpoint:
        """API endpoint configuration."""
        name: str
        base_url: str
        path: str
        method: HTTPMethod
        headers: Dict[str, str] = field(default_factory=dict)
        auth_required: bool = False
        description: str = ""
    
    
    @dataclass
    class APICall:
        """Track API calls."""
        endpoint: str
        method: str
        params: Dict[str, Any]
        response: Any
        status_code: int
        timestamp: datetime = field(default_factory=datetime.now)
        execution_time: float = 0.0
    
    
    class APIIntegrationPattern:
        """
        API Integration Pattern - Agent with API integration capabilities.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.llm = ChatOpenAI(model=model_name, temperature=0.3)
            self.endpoints: Dict[str, APIEndpoint] = {}
            self.call_history: List[APICall] = []
        
        def register_endpoint(self, endpoint: APIEndpoint):
            """Register an API endpoint."""
            self.endpoints[endpoint.name] = endpoint
        
        def call_api(self, endpoint_name: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
            """
            Simulate API call (in real implementation, would use requests library).
            """
            if endpoint_name not in self.endpoints:
                return {"error": f"Endpoint {endpoint_name} not found"}
            
            endpoint = self.endpoints[endpoint_name]
            params = params or {}
            
            # Simulate API response
            start = datetime.now()
            
            # Mock response based on endpoint
            mock_response = self._generate_mock_response(endpoint, params)
            
            execution_time = (datetime.now() - start).total_seconds()
            
            # Track call
            call = APICall(
                endpoint=endpoint_name,
                method=endpoint.method.value,
                params=params,
                response=mock_response,
                status_code=200,
                execution_time=execution_time
            )
            self.call_history.append(call)
            
            return {
                "endpoint": endpoint_name,
                "status": "success",
                "data": mock_response,
                "execution_time": execution_time
            }
        
        def _generate_mock_response(self, endpoint: APIEndpoint, params: Dict[str, Any]) -> Any:
            """Generate mock API response."""
            # Simulate different responses based on endpoint
            if "user" in endpoint.name.lower():
                return {"id": 1, "name": "John Doe", "email": "john@example.com"}
            elif "weather" in endpoint.name.lower():
                return {"temperature": 72, "condition": "sunny", "humidity": 45}
            elif "data" in endpoint.name.lower():
                return {"items": [{"id": i, "value": f"item_{i}"} for i in range(5)]}
            else:
                return {"message": "Success", "data": params}
        
        def run(self, task: str) -> Dict[str, Any]:
            """Execute task using API integration."""
            # Use LLM to decide which API to call
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You have access to these APIs: {list(self.endpoints.keys())}. Decide which to call based on the task."),
                ("human", "{task}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"task": task})
            
            # Simple parsing (in production, would use function calling)
            response_text = str(response.content)
            
            # Call APIs mentioned in response
            results = []
            for endpoint_name in self.endpoints.keys():
                if endpoint_name.lower() in response_text.lower():
                    result = self.call_api(endpoint_name)
                    results.append(result)
            
            return {
                "task": task,
                "endpoints_called": len(results),
                "results": results,
                "analysis": response.content
            }
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get API call statistics."""
            return {
                "total_calls": len(self.call_history),
                "endpoints_registered": len(self.endpoints),
                "calls_by_endpoint": {
                    name: sum(1 for call in self.call_history if call.endpoint == name)
                    for name in self.endpoints.keys()
                }
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== API Integration Pattern Demo ===\n")
        
        pattern = APIIntegrationPattern()
        
        # Register endpoints
        pattern.register_endpoint(APIEndpoint(
            name="GetUser",
            base_url="https://api.example.com",
            path="/users/{id}",
            method=HTTPMethod.GET,
            description="Fetch user information"
        ))
        
        pattern.register_endpoint(APIEndpoint(
            name="GetWeather",
            base_url="https://api.weather.com",
            path="/current",
            method=HTTPMethod.GET,
            description="Get current weather"
        ))
        
        pattern.register_endpoint(APIEndpoint(
            name="GetData",
            base_url="https://api.data.com",
            path="/items",
            method=HTTPMethod.GET,
            description="Fetch data items"
        ))
        
        # Test task
        result = pattern.run("Get user information and current weather")
        print(f"Task: {result['task']}")
        print(f"Endpoints called: {result['endpoints_called']}")
        print(f"\nResults:")
        for r in result['results']:
            print(f"  - {r['endpoint']}: {r['data']}")
        
        # Statistics
        print(f"\nStatistics: {pattern.get_statistics()}")
    
        

    Agentic Architecture Pattern: Api Integration

    Pattern 94: 94 Api Integration – Line-by-Line Explanation

    Overview

    Pattern 94: API Integration Pattern

    Agents that integrate with external APIs (REST, GraphQL, etc.) to fetch data, trigger actions, or interact with external systems.


    Code Structure Analysis

    File Information

    • Pattern Number: 94
    • Pattern Name: 94 Api Integration
    • File Path: patterns\tool_resource\94_api_integration.py
    • Total Lines: 193

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 94: API Integration Pattern
    
    Agents that integrate with external APIs (REST, GraphQL, etc.) to fetch data,
    trigger actions, or interact with external systems.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 94 Api Integration pattern.


    Imports Section

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

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


    Enumerations

    HTTPMethod (Line 17)

    class HTTPMethod(Enum):
        GET
        POST
        PUT
        DELETE
        PATCH
    

    Purpose: HTTP methods.

    Values: – GET: Represents get – POST: Represents post – PUT: Represents put – DELETE: Represents delete – PATCH: Represents patch


    Classes

    HTTPMethod (Line 17)

    Description: HTTP methods.

    APIEndpoint (Line 27)

    Description: API endpoint configuration.

    APICall (Line 39)

    Description: Track API calls.

    APIIntegrationPattern (Line 50)

    Description: API Integration Pattern – Agent with API integration capabilities.

    Methods:

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

    Purpose: No method docstring.

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

    register_endpoint (Line 60)
    def register_endpoint(self, endpoint):
        """Register an API endpoint."""
    

    Purpose: Register an API endpoint.

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

    call_api (Line 64)
    def call_api(self, endpoint_name, params):
        """Simulate API call (in real implementation, would use requests library)."""
    

    Purpose: Simulate API call (in real implementation, would use requests library).

    Parameters: – self: Instance reference – endpoint_name: Parameter for endpoint_name – params: Parameter for params

    _generate_mock_response (Line 100)
    def _generate_mock_response(self, endpoint, params):
        """Generate mock API response."""
    

    Purpose: Generate mock API response.

    Parameters: – self: Instance reference – endpoint: Parameter for endpoint – params: Parameter for params

    run (Line 112)
    def run(self, task):
        """Execute task using API integration."""
    

    Purpose: Execute task using API integration.

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

    get_statistics (Line 140)
    def get_statistics(self):
        """Get API call statistics."""
    

    Purpose: Get API call statistics.

    Parameters: – self: Instance reference


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = HTTPMethod(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Function Calling

    
        """
    Pattern 93: Function Calling Pattern
    
    Agents directly call Python functions based on natural language requests.
    Uses OpenAI's function calling API to map queries to function invocations.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    import json
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langchain_core.utils.function_calling import convert_to_openai_function
    
    
    @dataclass
    class FunctionDefinition:
        """Definition of callable function."""
        name: str
        description: str
        function: Callable
        parameters: Dict[str, Any]
        returns: str
    
    
    @dataclass
    class FunctionCall:
        """Record of function call."""
        call_id: str
        function_name: str
        arguments: Dict[str, Any]
        result: Any
        success: bool
        timestamp: datetime = field(default_factory=datetime.now)
        error: Optional[str] = None
    
    
    # Example functions that agents can call
    def calculate_discount(price: float, discount_percent: float) -> float:
        """Calculate final price after discount.
        
        Args:
            price: Original price
            discount_percent: Discount percentage (0-100)
        
        Returns:
            Final price after discount
        """
        return price * (1 - discount_percent / 100)
    
    
    def schedule_meeting(date: str, time: str, attendees: List[str], topic: str) -> str:
        """Schedule a meeting.
        
        Args:
            date: Meeting date (YYYY-MM-DD)
            time: Meeting time (HH:MM)
            attendees: List of attendee names
            topic: Meeting topic
        
        Returns:
            Confirmation message
        """
        return f"Meeting scheduled for {date} at {time} with {len(attendees)} attendees. Topic: {topic}"
    
    
    def send_email(to: str, subject: str, body: str) -> str:
        """Send an email.
        
        Args:
            to: Recipient email address
            subject: Email subject
            body: Email body
        
        Returns:
            Confirmation message
        """
        return f"Email sent to {to} with subject '{subject}'"
    
    
    def query_database(table: str, filters: Dict[str, Any]) -> List[Dict]:
        """Query database table.
        
        Args:
            table: Table name
            filters: Dictionary of filter conditions
        
        Returns:
            List of matching records
        """
        # Simulated database query
        return [
            {"id": 1, "name": "Record 1", "value": 100},
            {"id": 2, "name": "Record 2", "value": 200}
        ]
    
    
    def create_report(report_type: str, data_source: str, format: str = "pdf") -> str:
        """Generate a report.
        
        Args:
            report_type: Type of report (sales, analytics, etc.)
            data_source: Data source name
            format: Output format (pdf, excel, html)
        
        Returns:
            Report generation confirmation
        """
        return f"Generated {report_type} report from {data_source} in {format} format"
    
    
    class FunctionCallingAgent:
        """Agent that can call functions based on natural language."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0)
            self.functions: Dict[str, FunctionDefinition] = {}
            self.call_history: List[FunctionCall] = []
        
        def register_function(self, func_def: FunctionDefinition):
            """Register a function that can be called."""
            self.functions[func_def.name] = func_def
        
        def execute_query(self, query: str) -> Dict[str, Any]:
            """Execute natural language query by calling appropriate functions."""
            
            # Prepare function descriptions for LLM
            functions_for_llm = []
            for func_def in self.functions.values():
                functions_for_llm.append({
                    "name": func_def.name,
                    "description": func_def.description,
                    "parameters": func_def.parameters
                })
            
            # Create LLM with function calling
            llm_with_functions = self.llm.bind(functions=functions_for_llm)
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, an AI assistant that can call functions to help users. "
                          f"Analyze the user's request and call the appropriate function."),
                ("human", "{query}")
            ])
            
            chain = prompt | llm_with_functions
            
            try:
                response = chain.invoke({"query": query})
                
                # Check if function was called
                if hasattr(response, 'additional_kwargs') and 'function_call' in response.additional_kwargs:
                    function_call = response.additional_kwargs['function_call']
                    function_name = function_call['name']
                    arguments = json.loads(function_call['arguments'])
                    
                    # Execute the function
                    if function_name in self.functions:
                        func_def = self.functions[function_name]
                        result = func_def.function(**arguments)
                        
                        # Record call
                        call = FunctionCall(
                            call_id=f"call_{len(self.call_history)}",
                            function_name=function_name,
                            arguments=arguments,
                            result=result,
                            success=True
                        )
                        self.call_history.append(call)
                        
                        return {
                            "success": True,
                            "function_called": function_name,
                            "arguments": arguments,
                            "result": result,
                            "agent": self.name
                        }
                    else:
                        return {
                            "success": False,
                            "error": f"Function {function_name} not registered"
                        }
                else:
                    # No function called, just return text response
                    return {
                        "success": True,
                        "response": str(response.content),
                        "function_called": None
                    }
            
            except Exception as e:
                call = FunctionCall(
                    call_id=f"call_{len(self.call_history)}",
                    function_name="unknown",
                    arguments={},
                    result=None,
                    success=False,
                    error=str(e)
                )
                self.call_history.append(call)
                
                return {
                    "success": False,
                    "error": str(e)
                }
    
    
    class FunctionCallingPattern:
        """
        Function Calling Pattern - Natural language to function execution.
        
        Agents interpret natural language requests and automatically call
        appropriate Python functions with correct parameters.
        """
        
        def __init__(self):
            self.agents: Dict[str, FunctionCallingAgent] = {}
            self.available_functions: Dict[str, FunctionDefinition] = {}
        
        def register_function(self, func: Callable, description: str):
            """Register a function for agents to call."""
            # Extract function signature
            import inspect
            sig = inspect.signature(func)
            
            # Build parameter schema
            parameters = {
                "type": "object",
                "properties": {},
                "required": []
            }
            
            for param_name, param in sig.parameters.items():
                if param_name != 'self':
                    param_type = "string"  # Simplified
                    if param.annotation in [int, float]:
                        param_type = "number"
                    elif param.annotation == bool:
                        param_type = "boolean"
                    elif param.annotation == list:
                        param_type = "array"
                    
                    parameters["properties"][param_name] = {
                        "type": param_type,
                        "description": f"Parameter {param_name}"
                    }
                    
                    if param.default == inspect.Parameter.empty:
                        parameters["required"].append(param_name)
            
            func_def = FunctionDefinition(
                name=func.__name__,
                description=description,
                function=func,
                parameters=parameters,
                returns="Function result"
            )
            
            self.available_functions[func.__name__] = func_def
        
        def create_agent(self, name: str, function_names: Optional[List[str]] = None) -> FunctionCallingAgent:
            """Create agent with access to specified functions."""
            agent = FunctionCallingAgent(name)
            
            # Register functions to agent
            if function_names:
                for func_name in function_names:
                    if func_name in self.available_functions:
                        agent.register_function(self.available_functions[func_name])
            else:
                # Register all functions
                for func_def in self.available_functions.values():
                    agent.register_function(func_def)
            
            self.agents[name] = agent
            return agent
        
        def execute_query(self, agent_name: str, query: str) -> Dict[str, Any]:
            """Execute query with specified agent."""
            if agent_name not in self.agents:
                return {"success": False, "error": "Agent not found"}
            
            agent = self.agents[agent_name]
            result = agent.execute_query(query)
            
            if result.get("success"):
                if result.get("function_called"):
                    print(f"\n   ✓ {agent_name} called {result['function_called']}")
                    print(f"     Arguments: {result['arguments']}")
                    print(f"     Result: {result['result']}")
                else:
                    print(f"\n   ℹ️ {agent_name}: {result.get('response', 'No response')[:80]}")
            else:
                print(f"\n   ✗ {agent_name}: {result.get('error', 'Unknown error')}")
            
            return result
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute function calling pattern."""
            total_calls = sum(len(agent.call_history) for agent in self.agents.values())
            successful_calls = sum(
                sum(1 for call in agent.call_history if call.success)
                for agent in self.agents.values()
            )
            
            return {
                "pattern": "FunctionCalling",
                "total_agents": len(self.agents),
                "available_functions": len(self.available_functions),
                "total_calls": total_calls,
                "successful_calls": successful_calls,
                "scenario": scenario
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Function Calling Pattern Demo ===\n")
        
        # Create pattern
        pattern = FunctionCallingPattern()
        
        # Register functions
        print("1. Registering callable functions...")
        pattern.register_function(calculate_discount, "Calculate final price after applying discount")
        pattern.register_function(schedule_meeting, "Schedule a meeting with date, time, and attendees")
        pattern.register_function(send_email, "Send an email to a recipient")
        pattern.register_function(query_database, "Query database table with filters")
        pattern.register_function(create_report, "Generate a report from data source")
        
        print(f"   Registered {len(pattern.available_functions)} functions")
        
        # Create agents
        print("\n2. Creating function-calling agents...")
        assistant = pattern.create_agent("VirtualAssistant")
        print(f"   VirtualAssistant: {len(assistant.functions)} functions available")
        
        # Execute natural language queries
        print("\n3. Executing natural language queries...")
        
        queries = [
            "Calculate the final price for an item that costs $100 with a 20% discount",
            "Schedule a meeting for tomorrow at 2pm with Alice, Bob, and Carol to discuss Q4 planning",
            "Send an email to john@example.com with subject 'Project Update' and body 'The project is on track'",
            "Query the customers table and filter by status active",
            "Create a sales report from the Q4 data in PDF format"
        ]
        
        for query in queries:
            print(f"\n   Query: {query}")
            pattern.execute_query("VirtualAssistant", query)
        
        # Summary
        print("\n4. Execution Summary:")
        summary = pattern.run("Virtual assistant with function calling")
        print(f"   Total Functions: {summary['available_functions']}")
        print(f"   Function Calls: {summary['total_calls']}")
        print(f"   Successful: {summary['successful_calls']}")
        
        print("\n5. Call History:")
        for call in assistant.call_history:
            status = "✓" if call.success else "✗"
            print(f"   {status} {call.function_name}: {call.arguments}")
        
        print("\n✓ Function calling pattern executed natural language to function calls!")
    
        

    Agentic Architecture Pattern: Function Calling

    Pattern 93: 93 Function Calling – Line-by-Line Explanation

    Overview

    Pattern 93: Function Calling Pattern

    Agents directly call Python functions based on natural language requests. Uses OpenAI’s function calling API to map queries to function invocations.


    Code Structure Analysis

    File Information

    • Pattern Number: 93
    • Pattern Name: 93 Function Calling
    • File Path: patterns\tool_resource\93_function_calling.py
    • Total Lines: 368

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 93: Function Calling Pattern
    
    Agents directly call Python functions based on natural language requests.
    Uses OpenAI's function calling API to map queries to function invocations.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 93 Function Calling pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    import json
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langchain_core.utils.function_calling import convert_to_openai_function
            import inspect  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional, Callable: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from datetime import datetime: Date and time utilities – import json: JSON parsing and serialization – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration – from langchain_core.utils.function_calling import convert_to_openai_function: LangChain framework integration


    Classes

    FunctionDefinition (Line 18)

    Description: Definition of callable function.

    FunctionCall (Line 28)

    Description: Record of function call.

    FunctionCallingAgent (Line 113)

    Description: Agent that can call functions based on natural language.

    Methods:

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

    Purpose: No method docstring.

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

    register_function (Line 122)
    def register_function(self, func_def):
        """Register a function that can be called."""
    

    Purpose: Register a function that can be called.

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

    execute_query (Line 126)
    def execute_query(self, query):
        """Execute natural language query by calling appropriate functions."""
    

    Purpose: Execute natural language query by calling appropriate functions.

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

    FunctionCallingPattern (Line 210)

    Description: Function Calling Pattern – Natural language to function execution.

    Agents interpret natural language requests and automatically call appropriate Python functions with correct parameters.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_function (Line 222)
    def register_function(self, func, description):
        """Register a function for agents to call."""
    

    Purpose: Register a function for agents to call.

    Parameters: – self: Instance reference – func: Parameter for func – description: Parameter for description

    create_agent (Line 263)
    def create_agent(self, name, function_names):
        """Create agent with access to specified functions."""
    

    Purpose: Create agent with access to specified functions.

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

    execute_query (Line 280)
    def execute_query(self, agent_name, query):
        """Execute query with specified agent."""
    

    Purpose: Execute query with specified agent.

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

    run (Line 300)
    def run(self, scenario):
        """Execute function calling pattern."""
    

    Purpose: Execute function calling pattern.

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


    Functions

    calculate_discount (Line 40)

    def calculate_discount(price, discount_percent):
        """Calculate final price after discount.
    
    Args:
        price: Original price
        discount_percent: Discount percentage (0-100)
    
    Returns:
        Final price after discount"""
    

    Purpose: Calculate final price after discount.

    Args: price: Original price discount_percent: Discount percentage (0-100)

    Returns: Final price after discount

    schedule_meeting (Line 53)

    def schedule_meeting(date, time, attendees, topic):
        """Schedule a meeting.
    
    Args:
        date: Meeting date (YYYY-MM-DD)
        time: Meeting time (HH:MM)
        attendees: List of attendee names
        topic: Meeting topic
    
    Returns:
        Confirmation message"""
    

    Purpose: Schedule a meeting.

    Args: date: Meeting date (YYYY-MM-DD) time: Meeting time (HH:MM) attendees: List of attendee names topic: Meeting topic

    Returns: Confirmation message

    send_email (Line 68)

    def send_email(to, subject, body):
        """Send an email.
    
    Args:
        to: Recipient email address
        subject: Email subject
        body: Email body
    
    Returns:
        Confirmation message"""
    

    Purpose: Send an email.

    Args: to: Recipient email address subject: Email subject body: Email body

    Returns: Confirmation message

    query_database (Line 82)

    def query_database(table, filters):
        """Query database table.
    
    Args:
        table: Table name
        filters: Dictionary of filter conditions
    
    Returns:
        List of matching records"""
    

    Purpose: Query database table.

    Args: table: Table name filters: Dictionary of filter conditions

    Returns: List of matching records

    create_report (Line 99)

    def create_report(report_type, data_source, format):
        """Generate a report.
    
    Args:
        report_type: Type of report (sales, analytics, etc.)
        data_source: Data source name
        format: Output format (pdf, excel, html)
    
    Returns:
        Report generation confirmation"""
    

    Purpose: Generate a report.

    Args: report_type: Type of report (sales, analytics, etc.) data_source: Data source name format: Output format (pdf, excel, html)

    Returns: Report generation confirmation


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = FunctionDefinition(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Tool Augmented

    
        """
    Pattern 92: Tool Augmented
    
    Purpose: Enhanced implementation with full LangChain/LangGraph integration
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langgraph.graph import StateGraph, END
    from typing_extensions import TypedDict
    
    
    @dataclass
    class ToolAugmentedConfig:
        """Configuration for Tool Augmented."""
        model_name: str = "gpt-4"
        temperature: float = 0.7
        max_iterations: int = 10
        enable_logging: bool = True
    
    
    @dataclass
    class ToolAugmentedState:
        """State information for Tool Augmented."""
        current_step: int = 0
        data: Dict[str, Any] = field(default_factory=dict)
        results: List[Any] = field(default_factory=list)
        metadata: Dict[str, Any] = field(default_factory=dict)
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class ToolAugmentedAgent:
        """Agent implementing Tool Augmented."""
        
        def __init__(self, name: str, config: ToolAugmentedConfig = None):
            self.name = name
            self.config = config or ToolAugmentedConfig()
            self.llm = ChatOpenAI(
                model=self.config.model_name,
                temperature=self.config.temperature
            )
            self.state = ToolAugmentedState()
            self.execution_history: List[Dict[str, Any]] = []
        
        def process(self, input_data: Any) -> Dict[str, Any]:
            """Process input according to Tool Augmented."""
            self.state.current_step += 1
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, implementing Tool Augmented. "
                          f"Provide clear, structured responses."),
                ("human", "Process this input: {input_data}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"input_data": str(input_data)})
            
            result = {
                "agent": self.name,
                "step": self.state.current_step,
                "input": input_data,
                "output": str(response.content),
                "timestamp": datetime.now()
            }
            
            self.execution_history.append(result)
            self.state.results.append(result)
            
            return result
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get agent statistics."""
            return {
                "name": self.name,
                "total_executions": len(self.execution_history),
                "current_step": self.state.current_step,
                "results_count": len(self.state.results)
            }
    
    
    class ToolAugmentedPattern:
        """
        Tool Augmented - Enhanced implementation
        
        This pattern provides comprehensive functionality for tool augmented
        with full LangChain/LangGraph integration.
        
        Features:
        - Multi-agent coordination
        - State management
        - Execution tracking
        - LangGraph workflow integration
        """
        
        def __init__(self, config: ToolAugmentedConfig = None):
            self.config = config or ToolAugmentedConfig()
            self.agents: Dict[str, ToolAugmentedAgent] = {}
            self.workflow = self._build_workflow()
            self.execution_log: List[Dict[str, Any]] = []
        
        def _build_workflow(self) -> StateGraph:
            """Build LangGraph workflow for pattern execution."""
            
            class WorkflowState(TypedDict):
                input: str
                processed: str
                output: str
                metadata: Dict[str, Any]
            
            def process_input(state: WorkflowState) -> WorkflowState:
                """Process input node."""
                return {
                    **state,
                    "processed": f"Processed: {state['input']}",
                    "metadata": {"step": "process_input"}
                }
            
            def generate_output(state: WorkflowState) -> WorkflowState:
                """Generate output node."""
                llm = ChatOpenAI(model=self.config.model_name, temperature=self.config.temperature)
                
                prompt = ChatPromptTemplate.from_messages([
                    ("system", "You are implementing Tool Augmented. Generate comprehensive output."),
                    ("human", "{input}")
                ])
                
                chain = prompt | llm
                response = chain.invoke({"input": state["processed"]})
                
                return {
                    **state,
                    "output": str(response.content),
                    "metadata": {**state.get("metadata", {}), "step": "generate_output"}
                }
            
            # Build workflow graph
            workflow = StateGraph(WorkflowState)
            workflow.add_node("process", process_input)
            workflow.add_node("generate", generate_output)
            workflow.set_entry_point("process")
            workflow.add_edge("process", "generate")
            workflow.add_edge("generate", END)
            
            return workflow.compile()
        
        def register_agent(self, agent: ToolAugmentedAgent):
            """Register an agent with the pattern."""
            self.agents[agent.name] = agent
            if self.config.enable_logging:
                print(f"Registered agent: {agent.name}")
        
        def execute(self, input_data: Any, agent_name: str = None) -> Dict[str, Any]:
            """Execute the pattern with given input."""
            
            # Use workflow if no specific agent requested
            if agent_name is None:
                result = self.workflow.invoke({
                    "input": str(input_data),
                    "processed": "",
                    "output": "",
                    "metadata": {}
                })
                
                execution_record = {
                    "pattern": "Tool Augmented",
                    "input": input_data,
                    "output": result.get("output", ""),
                    "metadata": result.get("metadata", {}),
                    "timestamp": datetime.now()
                }
                
                self.execution_log.append(execution_record)
                return execution_record
            
            # Execute with specific agent
            agent = self.agents.get(agent_name)
            if not agent:
                raise ValueError(f"Agent {agent_name} not found")
            
            result = agent.process(input_data)
            self.execution_log.append(result)
            return result
        
        def run(self, input_data: Any) -> Dict[str, Any]:
            """Main execution method."""
            return self.execute(input_data)
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get pattern statistics."""
            return {
                "pattern": "Tool Augmented",
                "total_executions": len(self.execution_log),
                "registered_agents": len(self.agents),
                "agents": [agent.get_statistics() for agent in self.agents.values()]
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Tool Augmented Demo ===\n")
        
        # Create configuration
        config = ToolAugmentedConfig(
            model_name="gpt-4",
            temperature=0.7,
            enable_logging=True
        )
        
        # Create pattern
        pattern = ToolAugmentedPattern(config)
        
        # Create and register agents
        agent1 = ToolAugmentedAgent("Agent1", config)
        agent2 = ToolAugmentedAgent("Agent2", config)
        pattern.register_agent(agent1)
        pattern.register_agent(agent2)
        
        print("\nExecuting pattern workflow...")
        
        # Execute with workflow
        result1 = pattern.run("Demonstrate tool augmented functionality")
        print(f"\nWorkflow Result:")
        print(f"  Output: {result1['output'][:150]}...")
        
        # Execute with specific agents
        result2 = pattern.execute("Specific task for Agent1", agent_name="Agent1")
        print(f"\nAgent1 Result:")
        print(f"  Output: {result2['output'][:150]}...")
        
        result3 = pattern.execute("Specific task for Agent2", agent_name="Agent2")
        print(f"\nAgent2 Result:")
        print(f"  Output: {result3['output'][:150]}...")
        
        # Show statistics
        print("\n=== Statistics ===")
        stats = pattern.get_statistics()
        print(f"Pattern: {stats['pattern']}")
        print(f"Total Executions: {stats['total_executions']}")
        print(f"Registered Agents: {stats['registered_agents']}")
        print(f"\nAgent Statistics:")
        for agent_stats in stats['agents']:
            print(f"  {agent_stats['name']}: {agent_stats['total_executions']} executions")
    
        

    Agentic Architecture Pattern: Tool Augmented

    Pattern 92: 92 Tool Augmented – Line-by-Line Explanation

    Overview

    Pattern 92: Tool Augmented

    Purpose: Enhanced implementation with full LangChain/LangGraph integration


    Code Structure Analysis

    File Information

    • Pattern Number: 92
    • Pattern Name: 92 Tool Augmented
    • File Path: patterns\tool_resource\92_tool_augmented.py
    • Total Lines: 247

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 92: Tool Augmented
    
    Purpose: Enhanced implementation with full LangChain/LangGraph integration
    """
    

    Explanation: This module docstring describes the purpose and key features of the 92 Tool Augmented pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langgraph.graph import StateGraph, END
    from typing_extensions import TypedDict  # First 20 imports shown
    

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


    Classes

    ToolAugmentedConfig (Line 18)

    Description: Configuration for Tool Augmented.

    ToolAugmentedState (Line 27)

    Description: State information for Tool Augmented.

    ToolAugmentedAgent (Line 36)

    Description: Agent implementing Tool Augmented.

    Methods:

    __init__ (Line 39)
    def __init__(self, name, config):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – name: Identifier or label – config: Configuration settings

    process (Line 49)
    def process(self, input_data):
        """Process input according to Tool Augmented."""
    

    Purpose: Process input according to Tool Augmented.

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

    get_statistics (Line 75)
    def get_statistics(self):
        """Get agent statistics."""
    

    Purpose: Get agent statistics.

    Parameters: – self: Instance reference

    ToolAugmentedPattern (Line 85)

    Description: Tool Augmented – Enhanced implementation

    This pattern provides comprehensive functionality for tool augmented with full LangChain/LangGraph integration.

    Features: – Multi-agent coordination – State management – Execution tracking – LangGraph workflow integration

    Methods:

    __init__ (Line 99)
    def __init__(self, config):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – config: Configuration settings

    _build_workflow (Line 105)
    def _build_workflow(self):
        """Build LangGraph workflow for pattern execution."""
    

    Purpose: Build LangGraph workflow for pattern execution.

    Parameters: – self: Instance reference

    register_agent (Line 150)
    def register_agent(self, agent):
        """Register an agent with the pattern."""
    

    Purpose: Register an agent with the pattern.

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

    execute (Line 156)
    def execute(self, input_data, agent_name):
        """Execute the pattern with given input."""
    

    Purpose: Execute the pattern with given input.

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

    run (Line 188)
    def run(self, input_data):
        """Main execution method."""
    

    Purpose: Main execution method.

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

    get_statistics (Line 192)
    def get_statistics(self):
        """Get pattern statistics."""
    

    Purpose: Get pattern statistics.

    Parameters: – self: Instance reference

    WorkflowState (Line 108)

    Description: No class docstring.


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = ToolAugmentedConfig(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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

  • Agentic Architecture Pattern: Tool Using Agent

    
        """
    Pattern 91: Tool-Using Agent Pattern
    
    Agents that can use external tools to extend their capabilities.
    Integrates with LangChain's tool system for dynamic tool selection and execution.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langchain.agents import AgentExecutor, create_openai_tools_agent
    from langchain_core.tools import Tool, StructuredTool
    from langchain.tools import tool
    
    
    @dataclass
    class ToolExecution:
        """Record of tool execution."""
        tool_name: str
        input_data: Any
        output: Any
        success: bool
        timestamp: datetime = field(default_factory=datetime.now)
        error: Optional[str] = None
    
    
    # Define some example tools
    @tool
    def calculator(expression: str) -> str:
        """Evaluate a mathematical expression. Input should be a valid Python expression."""
        try:
            result = eval(expression)
            return f"Result: {result}"
        except Exception as e:
            return f"Error: {str(e)}"
    
    
    @tool
    def web_search(query: str) -> str:
        """Search the web for information. Returns simulated search results."""
        # In real implementation, would call actual search API
        return f"Search results for '{query}': [Simulated] Found 3 relevant articles about {query}."
    
    
    @tool
    def get_weather(location: str) -> str:
        """Get current weather for a location."""
        # Simulated weather data
        return f"Weather in {location}: Sunny, 72°F (22°C), Light breeze"
    
    
    @tool
    def text_analyzer(text: str) -> str:
        """Analyze text and return statistics."""
        words = text.split()
        chars = len(text)
        return f"Analysis: {len(words)} words, {chars} characters, avg word length: {chars/len(words):.1f}"
    
    
    class ToolUsingAgent:
        """Agent that can use tools to accomplish tasks."""
        
        def __init__(self, name: str, tools: List[Tool], model_name: str = "gpt-4"):
            self.name = name
            self.tools = tools
            self.llm = ChatOpenAI(model=model_name, temperature=0)
            self.execution_history: List[ToolExecution] = []
            
            # Create prompt for tool-using agent
            self.prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {name}, an AI assistant with access to tools. "
                          f"Use the available tools to help answer questions accurately. "
                          f"Available tools: {', '.join([t.name for t in tools])}"),
                ("human", "{input}"),
                ("placeholder", "{agent_scratchpad}")
            ])
            
            # Create agent
            self.agent = create_openai_tools_agent(self.llm, self.tools, self.prompt)
            self.agent_executor = AgentExecutor(
                agent=self.agent,
                tools=self.tools,
                verbose=False,
                max_iterations=5
            )
        
        def execute_task(self, task: str) -> Dict[str, Any]:
            """Execute task using available tools."""
            try:
                result = self.agent_executor.invoke({"input": task})
                
                # Record execution
                execution = ToolExecution(
                    tool_name="agent_executor",
                    input_data=task,
                    output=result.get("output", ""),
                    success=True
                )
                self.execution_history.append(execution)
                
                return {
                    "success": True,
                    "agent": self.name,
                    "task": task,
                    "result": result.get("output", ""),
                    "tools_used": self._extract_tools_used(result)
                }
            
            except Exception as e:
                execution = ToolExecution(
                    tool_name="agent_executor",
                    input_data=task,
                    output=None,
                    success=False,
                    error=str(e)
                )
                self.execution_history.append(execution)
                
                return {
                    "success": False,
                    "agent": self.name,
                    "task": task,
                    "error": str(e)
                }
        
        def _extract_tools_used(self, result: Dict) -> List[str]:
            """Extract which tools were used from result."""
            # Simplified - in real implementation would parse intermediate steps
            tools_mentioned = []
            output = str(result.get("output", ""))
            for tool in self.tools:
                if tool.name.lower() in output.lower():
                    tools_mentioned.append(tool.name)
            return tools_mentioned
    
    
    class ToolUsingAgentPattern:
        """
        Tool-Using Agent Pattern - Extend agent capabilities with tools.
        
        Agents can dynamically select and use tools based on task requirements.
        Integrates with LangChain's tool system for seamless tool calling.
        """
        
        def __init__(self):
            self.agents: Dict[str, ToolUsingAgent] = {}
            self.available_tools: List[Tool] = []
        
        def register_tool(self, tool: Tool):
            """Register a tool for agents to use."""
            self.available_tools.append(tool)
        
        def create_agent(self, name: str, tool_names: Optional[List[str]] = None) -> ToolUsingAgent:
            """Create agent with specified tools."""
            # Select tools
            if tool_names:
                agent_tools = [t for t in self.available_tools if t.name in tool_names]
            else:
                agent_tools = self.available_tools.copy()
            
            agent = ToolUsingAgent(name, agent_tools)
            self.agents[name] = agent
            
            return agent
        
        def execute_with_agent(self, agent_name: str, task: str) -> Dict[str, Any]:
            """Execute task with specific agent."""
            if agent_name not in self.agents:
                return {"success": False, "error": "Agent not found"}
            
            agent = self.agents[agent_name]
            result = agent.execute_task(task)
            
            if result["success"]:
                print(f"\n   ✓ {agent_name}: {task[:60]}...")
                print(f"     Result: {result['result'][:100]}...")
                if result.get("tools_used"):
                    print(f"     Tools used: {', '.join(result['tools_used'])}")
            else:
                print(f"\n   ✗ {agent_name}: {result.get('error', 'Unknown error')}")
            
            return result
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute tool-using agent pattern."""
            total_executions = sum(len(agent.execution_history) for agent in self.agents.values())
            successful_executions = sum(
                sum(1 for e in agent.execution_history if e.success)
                for agent in self.agents.values()
            )
            
            return {
                "pattern": "ToolUsingAgent",
                "total_agents": len(self.agents),
                "available_tools": len(self.available_tools),
                "total_executions": total_executions,
                "successful_executions": successful_executions,
                "scenario": scenario
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Tool-Using Agent Pattern Demo ===\n")
        
        # Create pattern
        pattern = ToolUsingAgentPattern()
        
        # Register tools
        print("1. Registering tools...")
        pattern.register_tool(calculator)
        pattern.register_tool(web_search)
        pattern.register_tool(get_weather)
        pattern.register_tool(text_analyzer)
        
        print(f"   Registered {len(pattern.available_tools)} tools")
        
        # Create agents with different tool sets
        print("\n2. Creating tool-using agents...")
        
        # General agent with all tools
        general_agent = pattern.create_agent("GeneralAssistant")
        print(f"   - GeneralAssistant: {len(general_agent.tools)} tools")
        
        # Math specialist with calculator
        math_agent = pattern.create_agent("MathSpecialist", ["calculator"])
        print(f"   - MathSpecialist: {len(math_agent.tools)} tools")
        
        # Research agent with search
        research_agent = pattern.create_agent("ResearchAssistant", ["web_search", "text_analyzer"])
        print(f"   - ResearchAssistant: {len(research_agent.tools)} tools")
        
        # Execute tasks
        print("\n3. Executing tasks with tool-using agents...")
        
        # Math task
        pattern.execute_with_agent(
            "MathSpecialist",
            "Calculate the result of (123 + 456) * 2"
        )
        
        # Weather task
        pattern.execute_with_agent(
            "GeneralAssistant",
            "What's the weather like in San Francisco?"
        )
        
        # Research task
        pattern.execute_with_agent(
            "ResearchAssistant",
            "Search for information about artificial intelligence and analyze the query"
        )
        
        # Complex task requiring multiple tools
        pattern.execute_with_agent(
            "GeneralAssistant",
            "Calculate 15% tip on a $85 dinner bill, then tell me the weather in New York"
        )
        
        # Summary
        print("\n4. Pattern Summary:")
        summary = pattern.run("Multi-agent tool-using system")
        print(f"   Total Agents: {summary['total_agents']}")
        print(f"   Available Tools: {summary['available_tools']}")
        print(f"   Total Executions: {summary['total_executions']}")
        print(f"   Successful: {summary['successful_executions']}")
        
        print("\n✓ Tool-using agents successfully extended capabilities with tools!")
    
        

    Agentic Architecture Pattern: Tool Using Agent

    Pattern 91: 91 Tool Using Agent – Line-by-Line Explanation

    Overview

    Pattern 91: Tool-Using Agent Pattern

    Agents that can use external tools to extend their capabilities. Integrates with LangChain’s tool system for dynamic tool selection and execution.


    Code Structure Analysis

    File Information

    • Pattern Number: 91
    • Pattern Name: 91 Tool Using Agent
    • File Path: patterns\tool_resource\91_tool_using_agent.py
    • Total Lines: 271

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 91: Tool-Using Agent Pattern
    
    Agents that can use external tools to extend their capabilities.
    Integrates with LangChain's tool system for dynamic tool selection and execution.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 91 Tool Using Agent pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langchain.agents import AgentExecutor, create_openai_tools_agent
    from langchain_core.tools import Tool, StructuredTool
    from langchain.tools import tool  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional, Callable: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from datetime import datetime: Date and time utilities – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration – from langchain.agents import AgentExecutor, create_openai_tools_agent: LangChain framework integration – from langchain_core.tools import Tool, StructuredTool: LangChain framework integration – from langchain.tools import tool: LangChain framework integration


    Classes

    ToolExecution (Line 19)

    Description: Record of tool execution.

    ToolUsingAgent (Line 62)

    Description: Agent that can use tools to accomplish tasks.

    Methods:

    __init__ (Line 65)
    def __init__(self, name, tools, model_name):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    execute_task (Line 89)
    def execute_task(self, task):
        """Execute task using available tools."""
    

    Purpose: Execute task using available tools.

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

    _extract_tools_used (Line 128)
    def _extract_tools_used(self, result):
        """Extract which tools were used from result."""
    

    Purpose: Extract which tools were used from result.

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

    ToolUsingAgentPattern (Line 139)

    Description: Tool-Using Agent Pattern – Extend agent capabilities with tools.

    Agents can dynamically select and use tools based on task requirements. Integrates with LangChain’s tool system for seamless tool calling.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_tool (Line 151)
    def register_tool(self, tool):
        """Register a tool for agents to use."""
    

    Purpose: Register a tool for agents to use.

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

    create_agent (Line 155)
    def create_agent(self, name, tool_names):
        """Create agent with specified tools."""
    

    Purpose: Create agent with specified tools.

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

    execute_with_agent (Line 168)
    def execute_with_agent(self, agent_name, task):
        """Execute task with specific agent."""
    

    Purpose: Execute task with specific agent.

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

    run (Line 186)
    def run(self, scenario):
        """Execute tool-using agent pattern."""
    

    Purpose: Execute tool-using agent pattern.

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


    Functions

    calculator (Line 31)

    def calculator(expression):
        """Evaluate a mathematical expression. Input should be a valid Python expression."""
    

    Purpose: Evaluate a mathematical expression. Input should be a valid Python expression.

    web_search (Line 41)

    def web_search(query):
        """Search the web for information. Returns simulated search results."""
    

    Purpose: Search the web for information. Returns simulated search results.

    get_weather (Line 48)

    def get_weather(location):
        """Get current weather for a location."""
    

    Purpose: Get current weather for a location.

    text_analyzer (Line 55)

    def text_analyzer(text):
        """Analyze text and return statistics."""
    

    Purpose: Analyze text and return statistics.


    Design Patterns Used

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

    Usage Example

    # Initialize the pattern
    pattern = ToolExecution(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

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

    Extension Points

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