Agentic Architecture Pattern: Autonomous Agent

Written by

in


    """
Pattern 03: Autonomous Agent Pattern
An agent that operates independently without external control, making its own decisions.
"""

from typing import Dict, Any, List, Optional
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


@dataclass
class AutonomousGoal:
    """A goal the agent pursues autonomously."""
    description: str
    priority: int  # 1-10, higher is more important
    status: str = "pending"  # pending, in_progress, completed, abandoned
    created_at: datetime = field(default_factory=datetime.now)


class AutonomousAgentPattern:
    """
    Autonomous Agent that:
    - Sets and pursues its own goals
    - Makes independent decisions
    - Adapts to changing circumstances
    - Operates without external control
    """
    
    def __init__(self, name: str = "AutonomousAgent", model_name: str = "gpt-4"):
        self.name = name
        self.llm = ChatOpenAI(model=model_name, temperature=0.8)
        self.goals: List[AutonomousGoal] = []
        self.tools: List[Tool] = []
        self.knowledge_base: Dict[str, Any] = {}
        self.action_history: List[str] = []
        self.agent_executor = None
        
    def add_tool(self, tool: Tool):
        """Add a tool for autonomous use."""
        self.tools.append(tool)
        self._rebuild_agent()
    
    def _rebuild_agent(self):
        """Rebuild agent with current tools."""
        if not self.tools:
            return
            
        prompt = ChatPromptTemplate.from_messages([
            ("system", f"""You are {self.name}, an autonomous agent.
            You operate independently and make your own decisions.
            
            Your current goals (prioritized):
            {{goals}}
            
            Your knowledge:
            {{knowledge}}
            
            Make decisions autonomously to achieve your goals."""),
            ("human", "{input}"),
            ("placeholder", "{agent_scratchpad}"),
        ])
        
        agent = create_openai_tools_agent(self.llm, self.tools, prompt)
        self.agent_executor = AgentExecutor(agent=agent, tools=self.tools, verbose=True)
    
    def set_goal(self, description: str, priority: int = 5):
        """Set a new goal autonomously."""
        goal = AutonomousGoal(description=description, priority=priority)
        self.goals.append(goal)
        self.goals.sort(key=lambda g: g.priority, reverse=True)
        print(f"🎯 Goal set: {description} (priority: {priority})")
    
    def get_active_goals(self) -> List[AutonomousGoal]:
        """Get currently active goals."""
        return [g for g in self.goals if g.status in ["pending", "in_progress"]]
    
    def decide_next_action(self) -> str:
        """Autonomously decide the next action."""
        active_goals = self.get_active_goals()
        if not active_goals:
            return "No active goals"
        
        goals_str = "\n".join([f"- {g.description} (priority: {g.priority})" 
                               for g in active_goals])
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", f"""You are {self.name}. Decide the next best action.
            Goals: {goals_str}
            Knowledge: {self.knowledge_base}
            Recent actions: {self.action_history[-3:]}"""),
            ("human", "What should I do next to make progress on my highest priority goal?")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({})
        return str(response.content)
    
    def execute_autonomous_cycle(self) -> Dict[str, Any]:
        """Execute one autonomous decision-action cycle."""
        # Decide next action
        action = self.decide_next_action()
        
        # Execute if we have tools
        if self.agent_executor and self.get_active_goals():
            highest_goal = self.get_active_goals()[0]
            highest_goal.status = "in_progress"
            
            result = self.agent_executor.invoke({
                "input": action,
                "goals": str([g.description for g in self.get_active_goals()]),
                "knowledge": str(self.knowledge_base)
            })
            
            self.action_history.append(action)
            return {"action": action, "result": result, "goal": highest_goal.description}
        else:
            return {"action": action, "result": "No tools available", "goal": "None"}
    
    def learn(self, key: str, value: Any):
        """Add knowledge to the agent's knowledge base."""
        self.knowledge_base[key] = value
        print(f"📚 Learned: {key} = {value}")
    
    def complete_goal(self, goal_description: str):
        """Mark a goal as completed."""
        for goal in self.goals:
            if goal.description == goal_description:
                goal.status = "completed"
                print(f"✅ Goal completed: {goal_description}")
                break
    
    def run(self, initial_context: Optional[str] = None, cycles: int = 3) -> Dict[str, Any]:
        """
        Run the autonomous agent for specified cycles.
        
        Args:
            initial_context: Optional context to start with
            cycles: Number of autonomous cycles to execute
            
        Returns:
            Dictionary with execution results
        """
        if initial_context:
            self.learn("initial_context", initial_context)
        
        results = []
        for i in range(cycles):
            print(f"\n--- Cycle {i+1}/{cycles} ---")
            cycle_result = self.execute_autonomous_cycle()
            results.append(cycle_result)
        
        return {
            "agent": self.name,
            "cycles_executed": cycles,
            "results": results,
            "goals_status": [(g.description, g.status) for g in self.goals],
            "knowledge_acquired": len(self.knowledge_base)
        }


# Example usage
if __name__ == "__main__":
    print("\n=== Autonomous Agent Example ===")
    
    # Create autonomous agent
    agent = AutonomousAgentPattern(name="AutoBot")
    
    # Set autonomous goals
    agent.set_goal("Learn about the environment", priority=8)
    agent.set_goal("Optimize my performance", priority=6)
    agent.set_goal("Help users effectively", priority=9)
    
    # Provide tools
    def search_tool(query: str) -> str:
        """Simulate a search tool."""
        return f"Search results for '{query}': Found relevant information..."
    
    agent.add_tool(Tool(
        name="Search",
        func=search_tool,
        description="Search for information"
    ))
    
    # Give initial knowledge
    agent.learn("environment", "collaborative workspace")
    agent.learn("users", ["Alice", "Bob", "Carol"])
    
    # Run autonomous cycles
    result = agent.run(initial_context="I'm in a team workspace", cycles=2)
    
    print("\n=== Autonomous Agent Results ===")
    print(f"Agent: {result['agent']}")
    print(f"Cycles: {result['cycles_executed']}")
    print(f"\nGoals Status:")
    for goal_desc, status in result['goals_status']:
        print(f"  - {goal_desc}: {status}")
    print(f"\nKnowledge Items: {result['knowledge_acquired']}")

    

Agentic Architecture Pattern: Autonomous Agent

Pattern 03: 03 Autonomous Agent – Line-by-Line Explanation

Overview

Pattern 03: Autonomous Agent Pattern An agent that operates independently without external control, making its own decisions.


Code Structure Analysis

File Information

  • Pattern Number: 03
  • Pattern Name: 03 Autonomous Agent
  • File Path: patterns\core_agent\03_autonomous_agent.py
  • Total Lines: 202

Detailed Code Explanation

Module Docstring

"""
Pattern 03: Autonomous Agent Pattern
An agent that operates independently without external control, making its own decisions.
"""

Explanation: This module docstring describes the purpose and key features of the 03 Autonomous Agent pattern.


Imports Section

from typing import Dict, Any, List, Optional
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  # 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 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: LangChain framework integration


Classes

AutonomousGoal (Line 16)

Description: A goal the agent pursues autonomously.

AutonomousAgentPattern (Line 24)

Description: Autonomous Agent that: – Sets and pursues its own goals – Makes independent decisions – Adapts to changing circumstances – Operates without external control

Methods:

__init__ (Line 33)
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”)

add_tool (Line 42)
def add_tool(self, tool):
    """Add a tool for autonomous use."""

Purpose: Add a tool for autonomous use.

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

_rebuild_agent (Line 47)
def _rebuild_agent(self):
    """Rebuild agent with current tools."""

Purpose: Rebuild agent with current tools.

Parameters: – self: Instance reference

set_goal (Line 70)
def set_goal(self, description, priority):
    """Set a new goal autonomously."""

Purpose: Set a new goal autonomously.

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

get_active_goals (Line 77)
def get_active_goals(self):
    """Get currently active goals."""

Purpose: Get currently active goals.

Parameters: – self: Instance reference

decide_next_action (Line 81)
def decide_next_action(self):
    """Autonomously decide the next action."""

Purpose: Autonomously decide the next action.

Parameters: – self: Instance reference

execute_autonomous_cycle (Line 102)
def execute_autonomous_cycle(self):
    """Execute one autonomous decision-action cycle."""

Purpose: Execute one autonomous decision-action cycle.

Parameters: – self: Instance reference

learn (Line 123)
def learn(self, key, value):
    """Add knowledge to the agent's knowledge base."""

Purpose: Add knowledge to the agent’s knowledge base.

Parameters: – self: Instance reference – key: Parameter for key – value: Parameter for value

complete_goal (Line 128)
def complete_goal(self, goal_description):
    """Mark a goal as completed."""

Purpose: Mark a goal as completed.

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

run (Line 136)
def run(self, initial_context, cycles):
    """Run the autonomous agent for specified cycles.

Args:
    initial_context: Optional context to start with
    cycles: Number of autonomous cycles to execute

Returns:
    Dictionary with execution results"""

Purpose: Run the autonomous agent for specified cycles.

Args: initial_context: Optional context to start with cycles: Number of autonomous cycles to execute

Returns: Dictionary with execution results

Parameters: – self: Instance reference – initial_context: Parameter for initial_context – cycles: Parameter for cycles


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 = AutonomousGoal(name="example", model_name="gpt-4")

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

# Check results
print(result)

Key Concepts

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

Extension Points

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

Comments

Leave a Reply

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