Designing the Agent's Brain (Architecture) › Adding Decision Logic

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) › Adding Decision Logic
Reading section 4 of 14 · Adding Decision Logic · 2 minSection 4 of 14 · 2 min

Book contents

Section 4 of 14 · 2 min read

Designing the Agent's Brain (Architecture) › Adding Decision LogicOne section · Sections in this chapter4 / 14 ↓

Our minimal agent works, but it's not very smart about when to use different capabilities. Let's add some decision logic so the agent can choose between different actions based on the input.

In[4]:
Code
import os
import anthropic
import re

class DecisionAgent:
    def __init__(self, model="claude-sonnet-4-5"):
        self.client = anthropic.Anthropic()
        self.model = model
        self.conversation_history = []
        
    def needs_calculation(self, text):
        # Simple heuristic: look for math expressions
        return bool(re.search(r'\d+\s*[\+\-\*\/]\s*\d+', text))
    
    def calculate(self, expression):
        # Extract and evaluate the math expression
        match = re.search(r'(\d+)\s*([\+\-\*\/])\s*(\d+)', expression)
        if match:
            a, op, b = match.groups()
            a, b = int(a), int(b)
            if op == '+': return a + b
            elif op == '-': return a - b
            elif op == '*': return a * b
            elif op == '/': return a / b if b != 0 else "Error: division by zero"
        return None
    
    def run(self, user_input):
        # Update state
        self.conversation_history.append({
            "role": "user",
            "content": user_input
        })
        
        # Decision point: do we need a tool?
        if self.needs_calculation(user_input):
            # Use the calculator tool
            result = self.calculate(user_input)
            response_text = f"The answer is {result}"
            
            # Log what we did (observability)
            print(f"[Agent Decision] Used calculator tool: {result}")
        else:
            # Use the language model
            response = self.client.messages.create(
                model=self.model,
                messages=self.conversation_history,
                max_tokens=1024
            )
            response_text = response.content[0].text
            print(f"[Agent Decision] Used language model")
        
        # Update state with response
        self.conversation_history.append({
            "role": "assistant",
            "content": response_text
        })
        
        return response_text

## Try it out
agent = DecisionAgent()
print(agent.run("What's 156 * 23?"))
print(agent.run("What's the capital of Spain?"))
Out[4]:
Console
[Agent Decision] Used calculator tool: 3588
The answer is 3588
[Agent Decision] Used language model
The capital of Spain is Madrid.

Now our agent makes explicit decisions. Before generating a response, it checks whether the input looks like a math problem. If it does, the agent uses its calculator tool. Otherwise, it uses the language model.

This is a simple example, but it illustrates an important principle: your agent's architecture should make decisions visible and controllable. You're not just throwing everything at the model and hoping for the best. You're building a system that chooses the right approach for each situation.