Implementing Memory in Our Agent › Adding Tool Use with Memory

Michael BrenndoerferJuly 5, 20253 min read
AI Agent HandbookAll chapters
Part 6 of 15Memory and Retrieval - How Agents Remember
Chapter 17Implementing Memory in Our Agent › Adding Tool Use with Memory
Reading section 4 of 13 · Adding Tool Use with Memory · 3 minSection 4 of 13 · 3 min

Book contents

Section 4 of 13 · 3 min read

Implementing Memory in Our Agent › Adding Tool Use with MemoryOne section · Sections in this chapter4 / 13 ↓

Let's extend our assistant to use tools while maintaining memory. We'll add a calculator tool as an example:

In[2]:
Code
def calculate(expression: str) -> dict:
    """Calculator tool for mathematical operations."""
    try:
        result = eval(expression)
        return {"success": True, "result": result}
    except Exception as e:
        return {"success": False, "error": str(e)}

calculator_tool = {
    "name": "calculate",
    "description": "Perform mathematical calculations. Input should be a valid Python expression.",
    "input_schema": {
        "type": "object",
        "properties": {
            "expression": {
                "type": "string",
                "description": "Mathematical expression to evaluate (e.g., '2 + 2', '15 * 3.5')"
            }
        },
        "required": ["expression"]
    }
}

class PersonalAssistantWithTools:
    """Assistant with memory and tool use."""
    
    def __init__(self, api_key: str):
        self.client = Anthropic(api_key=api_key)
        self.model = "claude-sonnet-4-5"
        self.conversation = ConversationManager(max_messages=20)
        self.knowledge = SemanticKnowledgeStore()
        self.tools = {"calculate": calculate}
    
    def chat(self, user_message: str) -> str:
        """Process message with tool use support."""
        # Handle memory commands
        if self._is_memory_command(user_message):
            return self._handle_memory_command(user_message)
        
        # Search for relevant facts
        relevant_facts = self.knowledge.search(user_message)
        system_prompt = self._build_system_prompt(relevant_facts)
        
        # Add user message
        self.conversation.add_user_message(user_message)
        
        # Get response with tools
        response = self.client.messages.create(
            model=self.model,
            max_tokens=1024,
            system=system_prompt,
            tools=[calculator_tool],
            messages=self.conversation.get_messages()
        )
        
        # Handle tool use if needed
        while response.stop_reason == "tool_use":
            # Extract tool call
            tool_use_block = next(
                block for block in response.content 
                if block.type == "tool_use"
            )
            
            # Execute tool
            tool_result = self.tools[tool_use_block.name](
                **tool_use_block.input
            )
            
            # Add tool use to conversation
            self.conversation.add_assistant_message(response.content)
            
            # Add tool result
            self.conversation.messages.append({
                "role": "user",
                "content": [{
                    "type": "tool_result",
                    "tool_use_id": tool_use_block.id,
                    "content": str(tool_result)
                }]
            })
            
            # Get next response
            response = self.client.messages.create(
                model=self.model,
                max_tokens=1024,
                system=system_prompt,
                tools=[calculator_tool],
                messages=self.conversation.get_messages()
            )
        
        # Extract final response
        assistant_message = response.content[0].text
        self.conversation.add_assistant_message(assistant_message)
        
        return assistant_message
    
    # ... other methods same as before

Now watch memory and tools work together:

In[4]:
Code
assistant = PersonalAssistantWithTools(api_key=os.getenv("ANTHROPIC_API_KEY"))

## Store a fact
print(assistant.chat("Remember that I need to save \$500 per month"))
## Output: Got it! I'll remember that you need to save $500 per month

## Use tools with memory
print(assistant.chat("I earn \$3000 per month. After my savings goal, how much do I have left?"))
## Agent retrieves: "You need to save $500 per month"
## Agent uses calculator: 3000 - 500
## Output: After setting aside your $500 monthly savings goal, you'll have 
## $2,500 left for other expenses.

print(assistant.chat("If I split the remaining amount across 4 weeks, how much is that per week?"))
## Agent remembers previous calculation: $2,500
## Agent uses calculator: 2500 / 4
## Output: Splitting your remaining $2,500 across 4 weeks gives you $625 per week.

The assistant combines three capabilities:

  1. Long-term memory: Retrieves your savings goal
  2. Short-term memory: Remembers the previous calculation
  3. Tool use: Performs accurate calculations

This is powerful. The agent can reference stored facts, maintain conversation context, and use tools to solve problems it couldn't handle with language alone.