Agentic Architecture Pattern: Bdi

Written by

in


    """
Pattern 41: BDI (Belief-Desire-Intention) Pattern

Classic agent architecture with three mental states:
- Beliefs: What the agent knows about the world
- Desires: Goals the agent wants to achieve
- Intentions: Plans the agent commits to executing
"""

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 BeliefType(Enum):
    """Type of belief."""
    FACT = "fact"
    ASSUMPTION = "assumption"
    OBSERVATION = "observation"
    INFERENCE = "inference"


class DesireType(Enum):
    """Type of desire/goal."""
    ACHIEVEMENT = "achievement"
    MAINTENANCE = "maintenance"
    AVOIDANCE = "avoidance"


class IntentionStatus(Enum):
    """Status of intention."""
    ACTIVE = "active"
    SUSPENDED = "suspended"
    COMPLETED = "completed"
    FAILED = "failed"


@dataclass
class Belief:
    """Belief about the world."""
    belief_id: str
    content: str
    belief_type: BeliefType
    confidence: float = 1.0  # 0.0 to 1.0
    timestamp: datetime = field(default_factory=datetime.now)


@dataclass
class Desire:
    """Goal or desire."""
    desire_id: str
    description: str
    desire_type: DesireType
    priority: int = 5  # 1-10
    conditions: List[str] = field(default_factory=list)  # Success conditions


@dataclass
class Intention:
    """Committed plan."""
    intention_id: str
    desire_id: str
    plan_steps: List[str]
    current_step: int = 0
    status: IntentionStatus = IntentionStatus.ACTIVE


@dataclass
class Action:
    """Action executed by agent."""
    action_id: str
    description: str
    intention_id: str
    result: Optional[str] = None
    success: bool = False


class BDIAgent:
    """Agent with Belief-Desire-Intention architecture."""
    
    def __init__(self, name: str, model_name: str = "gpt-4"):
        self.name = name
        self.llm = ChatOpenAI(model=model_name, temperature=0.7)
        
        # BDI mental states
        self.beliefs: List[Belief] = []
        self.desires: List[Desire] = []
        self.intentions: List[Intention] = []
        self.actions: List[Action] = []
    
    def add_belief(self, belief: Belief):
        """Add or update belief."""
        # Remove conflicting beliefs (simplified)
        self.beliefs = [b for b in self.beliefs if b.content != belief.content]
        self.beliefs.append(belief)
    
    def add_desire(self, desire: Desire):
        """Add desire/goal."""
        self.desires.append(desire)
    
    def deliberate(self) -> Optional[Desire]:
        """Select most important desire to pursue."""
        if not self.desires:
            return None
        
        # Filter already-pursued desires
        active_desire_ids = {i.desire_id for i in self.intentions if i.status == IntentionStatus.ACTIVE}
        available_desires = [d for d in self.desires if d.desire_id not in active_desire_ids]
        
        if not available_desires:
            return None
        
        # Select highest priority
        selected = max(available_desires, key=lambda d: d.priority)
        return selected
    
    def means_end_reasoning(self, desire: Desire) -> List[str]:
        """Generate plan to achieve desire using beliefs."""
        beliefs_text = "\n".join([f"- {b.content} ({b.belief_type.value}, confidence: {b.confidence})" 
                                  for b in self.beliefs])
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", f"You are {self.name}, an intelligent agent. Generate a concrete plan to achieve a goal "
                      f"based on your beliefs about the world."),
            ("human", f"Current Beliefs:\n{beliefs_text}\n\n"
                     f"Goal: {desire.description} (Type: {desire.desire_type.value})\n"
                     f"Success conditions: {', '.join(desire.conditions)}\n\n"
                     f"Create a plan with 3-4 specific steps to achieve this goal.")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({})
        
        # Parse steps from response
        content = str(response.content)
        steps = []
        for line in content.split('\n'):
            line = line.strip()
            if line and (line[0].isdigit() or line.startswith('-') or line.startswith('*')):
                # Remove numbering/bullets
                step = line.lstrip('0123456789.-*) ').strip()
                if step:
                    steps.append(step)
        
        return steps[:4] if steps else ["Execute default action"]
    
    def commit_to_intention(self, desire: Desire, plan: List[str]):
        """Create intention from desire and plan."""
        intention = Intention(
            intention_id=f"int_{len(self.intentions)}",
            desire_id=desire.desire_id,
            plan_steps=plan,
            status=IntentionStatus.ACTIVE
        )
        self.intentions.append(intention)
        return intention
    
    def execute_intention(self, intention: Intention) -> bool:
        """Execute next step of intention."""
        if intention.status != IntentionStatus.ACTIVE:
            return False
        
        if intention.current_step >= len(intention.plan_steps):
            intention.status = IntentionStatus.COMPLETED
            return True
        
        # Execute current step
        step = intention.plan_steps[intention.current_step]
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", f"You are {self.name} executing a plan step."),
            ("human", f"Step: {step}\n\nDescribe briefly what you do to execute this step.")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({})
        
        action = Action(
            action_id=f"act_{len(self.actions)}",
            description=step,
            intention_id=intention.intention_id,
            result=str(response.content)[:150],
            success=True
        )
        self.actions.append(action)
        
        intention.current_step += 1
        
        return True
    
    def bdi_cycle(self):
        """Execute one BDI reasoning cycle."""
        # 1. Update beliefs (would normally perceive environment)
        print(f"\n   {self.name} BDI Cycle:")
        print(f"   Beliefs: {len(self.beliefs)}")
        print(f"   Desires: {len(self.desires)}")
        print(f"   Active Intentions: {sum(1 for i in self.intentions if i.status == IntentionStatus.ACTIVE)}")
        
        # 2. Deliberate: choose desire
        selected_desire = self.deliberate()
        
        if selected_desire:
            print(f"   ⚔ Selected desire: {selected_desire.description}")
            
            # 3. Means-end reasoning: create plan
            plan = self.means_end_reasoning(selected_desire)
            print(f"   šŸ“‹ Generated plan with {len(plan)} steps")
            
            # 4. Commit to intention
            intention = self.commit_to_intention(selected_desire, plan)
            print(f"   āœ“ Committed to intention: {intention.intention_id}")
        
        # 5. Execute active intentions
        active_intentions = [i for i in self.intentions if i.status == IntentionStatus.ACTIVE]
        for intention in active_intentions:
            if intention.current_step  Dict[str, Any]:
        """Execute BDI pattern."""
        total_beliefs = sum(len(agent.beliefs) for agent in self.agents.values())
        total_desires = sum(len(agent.desires) for agent in self.agents.values())
        total_intentions = sum(len(agent.intentions) for agent in self.agents.values())
        total_actions = sum(len(agent.actions) for agent in self.agents.values())
        
        return {
            "pattern": "BDI",
            "total_agents": len(self.agents),
            "total_beliefs": total_beliefs,
            "total_desires": total_desires,
            "total_intentions": total_intentions,
            "actions_executed": total_actions,
            "scenario": scenario
        }


# Example usage
if __name__ == "__main__":
    print("=== BDI (Belief-Desire-Intention) Pattern Demo ===\n")
    
    # Create BDI agent
    agent = BDIAgent("Alice")
    
    # Add beliefs about the world
    print("1. Setting up beliefs...")
    agent.add_belief(Belief("b1", "The weather is sunny", BeliefType.OBSERVATION, confidence=1.0))
    agent.add_belief(Belief("b2", "I have a bicycle", BeliefType.FACT, confidence=1.0))
    agent.add_belief(Belief("b3", "The park is 2km away", BeliefType.FACT, confidence=1.0))
    agent.add_belief(Belief("b4", "Exercise is healthy", BeliefType.INFERENCE, confidence=0.9))
    
    # Add desires/goals
    print("2. Setting up desires...")
    agent.add_desire(Desire(
        "d1",
        "Get physical exercise",
        DesireType.ACHIEVEMENT,
        priority=8,
        conditions=["30 minutes of activity", "increased heart rate"]
    ))
    
    agent.add_desire(Desire(
        "d2",
        "Enjoy outdoor activities",
        DesireType.ACHIEVEMENT,
        priority=6,
        conditions=["spend time outside", "have fun"]
    ))
    
    # Create pattern and register agent
    pattern = BDIPattern()
    pattern.register_agent(agent)
    
    # Run BDI cycles
    print("\n3. Running BDI cycles...")
    pattern.run_cycles(num_cycles=2)
    
    # Summary
    print("\n4. BDI Agent Summary:")
    summary = pattern.run("Personal health and recreation planning")
    print(f"   Total Agents: {summary['total_agents']}")
    print(f"   Beliefs: {summary['total_beliefs']}")
    print(f"   Desires: {summary['total_desires']}")
    print(f"   Intentions: {summary['total_intentions']}")
    print(f"   Actions Executed: {summary['actions_executed']}")
    
    print("\nāœ“ BDI pattern demonstrated rational agent reasoning!")

    

Agentic Architecture Pattern: Bdi

Pattern 41: 41 Bdi – Line-by-Line Explanation

Overview

Pattern 41: BDI (Belief-Desire-Intention) Pattern

Classic agent architecture with three mental states: – Beliefs: What the agent knows about the world – Desires: Goals the agent wants to achieve – Intentions: Plans the agent commits to executing


Code Structure Analysis

File Information

  • Pattern Number: 41
  • Pattern Name: 41 Bdi
  • File Path: patterns\decision_making\41_bdi.py
  • Total Lines: 321

Detailed Code Explanation

Module Docstring

"""
Pattern 41: BDI (Belief-Desire-Intention) Pattern

Classic agent architecture with three mental states:
- Beliefs: What the agent knows about the world
- Desires: Goals the agent wants to achieve
- Intentions: Plans the agent commits to executing
"""

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

BeliefType (Line 18)

class BeliefType(Enum):
    FACT
    ASSUMPTION
    OBSERVATION
    INFERENCE

Purpose: Type of belief.

Values: – FACT: Represents fact – ASSUMPTION: Represents assumption – OBSERVATION: Represents observation – INFERENCE: Represents inference

DesireType (Line 26)

class DesireType(Enum):
    ACHIEVEMENT
    MAINTENANCE
    AVOIDANCE

Purpose: Type of desire/goal.

Values: – ACHIEVEMENT: Represents achievement – MAINTENANCE: Represents maintenance – AVOIDANCE: Represents avoidance

IntentionStatus (Line 33)

class IntentionStatus(Enum):
    ACTIVE
    SUSPENDED
    COMPLETED
    FAILED

Purpose: Status of intention.

Values: – ACTIVE: Currently operational – SUSPENDED: Represents suspended – COMPLETED: Successfully finished – FAILED: Execution failed


Classes

BeliefType (Line 18)

Description: Type of belief.

DesireType (Line 26)

Description: Type of desire/goal.

IntentionStatus (Line 33)

Description: Status of intention.

Belief (Line 42)

Description: Belief about the world.

Desire (Line 52)

Description: Goal or desire.

Intention (Line 62)

Description: Committed plan.

Action (Line 72)

Description: Action executed by agent.

BDIAgent (Line 81)

Description: Agent with Belief-Desire-Intention architecture.

Methods:

__init__ (Line 84)
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_belief (Line 94)
def add_belief(self, belief):
    """Add or update belief."""

Purpose: Add or update belief.

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

add_desire (Line 100)
def add_desire(self, desire):
    """Add desire/goal."""

Purpose: Add desire/goal.

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

deliberate (Line 104)
def deliberate(self):
    """Select most important desire to pursue."""

Purpose: Select most important desire to pursue.

Parameters: – self: Instance reference

means_end_reasoning (Line 120)
def means_end_reasoning(self, desire):
    """Generate plan to achieve desire using beliefs."""

Purpose: Generate plan to achieve desire using beliefs.

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

commit_to_intention (Line 150)
def commit_to_intention(self, desire, plan):
    """Create intention from desire and plan."""

Purpose: Create intention from desire and plan.

Parameters: – self: Instance reference – desire: Parameter for desire – plan: Parameter for plan

execute_intention (Line 161)
def execute_intention(self, intention):
    """Execute next step of intention."""

Purpose: Execute next step of intention.

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

bdi_cycle (Line 194)
def bdi_cycle(self):
    """Execute one BDI reasoning cycle."""

Purpose: Execute one BDI reasoning cycle.

Parameters: – self: Instance reference

BDIPattern (Line 224)

Description: BDI (Belief-Desire-Intention) Pattern – Rational agent architecture.

Agents maintain beliefs about the world, have desires (goals), and commit to intentions (plans). The BDI cycle continuously: 1. Updates beliefs from perception 2. Deliberates to select goals 3. Generates plans through means-end reasoning 4. Executes committed intentions

Methods:

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

Purpose: No method docstring.

Parameters: – self: Instance reference

register_agent (Line 239)
def register_agent(self, agent):
    """Register BDI agent."""

Purpose: Register BDI agent.

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

run_cycles (Line 243)
def run_cycles(self, num_cycles):
    """Run BDI cycles for all agents."""

Purpose: Run BDI cycles for all agents.

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

run (Line 253)
def run(self, scenario):
    """Execute BDI pattern."""

Purpose: Execute BDI pattern.

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


Design Patterns Used

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

Usage Example

# Initialize the pattern
pattern = BeliefType(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 *