Designing the Agent's Brain (Architecture) › Structuring for Growth

Michael BrenndoerferJuly 9, 20252 min read
AI Agent HandbookAll chapters
Part 7 of 15Agent State and Architecture - Putting It All Together
Chapter 19Designing the Agent's Brain (Architecture) › Structuring for Growth
Reading section 5 of 14 · Structuring for Growth · 2 minSection 5 of 14 · 2 min

Book contents

Section 5 of 14 · 2 min read

Designing the Agent's Brain (Architecture) › Structuring for GrowthOne section · Sections in this chapter5 / 14 ↓

As your agent gets more capable, the decision logic gets more complex. You might have multiple tools, different reasoning strategies, and various ways to handle errors. If you're not careful, your code can become a tangled mess.

Here's a more organized architecture that scales better:

In[5]:
Code
import os
import anthropic
from typing import Dict, List, Optional

class Agent:
    def __init__(self, model="claude-sonnet-4-5"):
        self.client = anthropic.Anthropic()
        self.model = model
        self.state = {
            "conversation_history": [],
            "tools_used": [],
            "current_goal": None
        }
        
    def update_state(self, key, value):
        """Centralized state management"""
        self.state[key] = value
        
    def add_to_history(self, role, content):
        """Add a message to conversation history"""
        self.state["conversation_history"].append({
            "role": role,
            "content": content
        })
        
    def decide_action(self, user_input: str) -> str:
        """Decide what action to take"""
        # This is where you'd add more sophisticated logic
        if "calculate" in user_input.lower() or any(op in user_input for op in ['+', '-', '*', '/']):
            return "use_calculator"
        elif "remember" in user_input.lower():
            return "store_memory"
        else:
            return "use_model"
    
    def execute_action(self, action: str, user_input: str) -> str:
        """Execute the decided action"""
        if action == "use_calculator":
            return self.use_calculator(user_input)
        elif action == "store_memory":
            return self.store_memory(user_input)
        else:
            return self.use_model(user_input)
    
    def use_calculator(self, text: str) -> str:
        """Calculator tool"""
        # Simplified for example
        self.state["tools_used"].append("calculator")
        return "Calculator result: [implementation here]"
    
    def store_memory(self, text: str) -> str:
        """Memory storage tool"""
        self.state["tools_used"].append("memory")
        return "Stored in memory"
    
    def use_model(self, user_input: str) -> str:
        """Use the language model"""
        response = self.client.messages.create(
            model=self.model,
            messages=self.state["conversation_history"],
            max_tokens=1024
        )
        return response.content[0].text
    
    def run(self, user_input: str) -> str:
        """Main agent loop"""
        # 1. Receive and update state
        self.add_to_history("user", user_input)
        
        # 2. Decide what to do
        action = self.decide_action(user_input)
        print(f"[Agent] Decided to: {action}")
        
        # 3. Execute the action
        response = self.execute_action(action, user_input)
        
        # 4. Update state with response
        self.add_to_history("assistant", response)
        
        # 5. Return response
        return response

## Usage
agent = Agent()
print(agent.run("What's 50 + 30?"))
print(agent.run("What's the weather like?"))
Out[5]:
Console
[Agent] Decided to: use_calculator
Calculator result: [implementation here]
[Agent] Decided to: use_model
I don't have access to real-time weather information. To get current weather conditions, you could:

1. Check a weather website like weather.com or weather.gov
2. Use a weather app on your phone
3. Search "weather" along with your location in a search engine
4. Ask a voice assistant that has internet access

If you let me know your location, I can discuss typical weather patterns for that area, but I won't be able to tell you today's specific conditions.

This architecture separates concerns cleanly:

  • State management is centralized in update_state() and add_to_history()
  • Decision logic lives in decide_action()
  • Action execution is handled by execute_action() and specific tool methods
  • The main loop in run() orchestrates everything

When you want to add a new capability, you know exactly where it goes. Need a new tool? Add it to execute_action(). Need a new decision rule? Update decide_action(). Want to track something new? Add it to the state dictionary.