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
Designing the Agent's Brain (Architecture) › Structuring for GrowthOne section · Sections in this chapter5 / 14 ↓
Sections in this chapter14
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]:
Codeimport 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()andadd_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.