"""
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
Leave a Reply