Skip to content
Learning Lab · 5 min read

Building AI Agents: The Three Patterns That Actually Work

Three architecture patterns for AI agents, from simple tool routing to agentic loops. Learn how to structure tool calling, set memory limits, and avoid the most common failure modes—with working code.

AI Agent Architecture: Patterns, Tool Calling, Memory

Last month I watched an agent spend 47 API calls trying to answer a question it could have resolved in two. The setup looked reasonable—tool calling enabled, memory buffer in place, error handling on paper. The agent just had no idea which tool to use first, kept calling the same thing, and had no way to know it was looping.

This is what happens when you build an agent without understanding its actual failure modes. Architecture matters. Here’s what I’ve learned from shipping agents into production.

The Three Core Patterns

An AI agent needs three things to work: a way to decide what to do, access to tools, and memory of what happened. The way you connect these three things determines whether your agent runs clean or burns through tokens chasing its tail.

Pattern 1: Simple Routing (Decision → Tool → Response)

This is the foundation. The agent sees a user request, picks a tool, executes it, and returns a result. No loops. No recursion. Single decision point.

from anthropic import Anthropic

client = Anthropic()

def route_and_execute(user_message: str) -> str:
    tools = [
        {
            "name": "lookup_price",
            "description": "Get current price for a product",
            "input_schema": {
                "type": "object",
                "properties": {
                    "product_id": {"type": "string"}
                },
                "required": ["product_id"]
            }
        },
        {
            "name": "check_stock",
            "description": "Check inventory for a product",
            "input_schema": {
                "type": "object",
                "properties": {
                    "product_id": {"type": "string"}
                },
                "required": ["product_id"]
            }
        }
    ]
    
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        tools=tools,
        messages=[{
            "role": "user",
            "content": user_message
        }]
    )
    
    # Check response type
    for block in response.content:
        if block.type == "tool_use":
            tool_name = block.name
            tool_input = block.input
            
            # Execute tool (mock implementation)
            if tool_name == "lookup_price":
                result = f"Price for {tool_input['product_id']}: $29.99"
            elif tool_name == "check_stock":
                result = f"Stock for {tool_input['product_id']}: 15 units"
            else:
                result = "Tool not found"
            
            return result
    
    # If no tool was called, return text response
    return response.content[0].text if response.content else ""

# Usage
response = route_and_execute("What's the price of product ABC-123?")
print(response)

This works well for straightforward tasks—customer service queries, data lookups, single decisions. It fails when the answer requires multiple steps.

Pattern 2: Agentic Loop (Decide → Tool → Evaluate → Decide Again)

When a task needs multiple steps—research something, then calculate, then format—you need a loop. The agent makes a decision, executes it, gets feedback, and decides what to do next. The trap: without exit conditions, this becomes infinite.

def agentic_loop(user_message: str, max_iterations: int = 5) -> str:
    tools = [
        {
            "name": "search_knowledge_base",
            "description": "Search internal docs for information",
            "input_schema": {
                "type": "object",
                "properties": {
                    "query": {"type": "string"}
                },
                "required": ["query"]
            }
        },
        {
            "name": "calculate_metric",
            "description": "Perform calculation on data",
            "input_schema": {
                "type": "object",
                "properties": {
                    "values": {"type": "array", "items": {"type": "number"}},
                    "operation": {"type": "string", "enum": ["sum", "average", "max"]}
                },
                "required": ["values", "operation"]
            }
        }
    ]
    
    messages = [{
        "role": "user",
        "content": user_message
    }]
    
    for iteration in range(max_iterations):
        response = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1024,
            tools=tools,
            messages=messages
        )
        
        # Check if we have a final answer
        if response.stop_reason == "end_turn":
            return response.content[0].text if response.content else ""
        
        # Process tool calls
        if response.stop_reason == "tool_use":
            # Add assistant response to message history
            messages.append({
                "role": "assistant",
                "content": response.content
            })
            
            # Execute tools and collect results
            tool_results = []
            for block in response.content:
                if block.type == "tool_use":
                    # Mock execution
                    if block.name == "search_knowledge_base":
                        result = f"Found docs on: {block.input['query']}"
                    elif block.name == "calculate_metric":
                        values = block.input['values']
                        op = block.input['operation']
                        if op == "sum":
                            result = f"Result: {sum(values)}"
                        elif op == "average":
                            result = f"Result: {sum(values)/len(values)}"
                        else:
                            result = f"Result: {max(values)}"
                    else:
                        result = "Unknown tool"
                    
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": result
                    })
            
            # Add tool results back to messages
            messages.append({
                "role": "user",
                "content": tool_results
            })
    
    return "Max iterations reached"

# Usage
result = agentic_loop("Find our Q3 revenue data and calculate the average monthly value")
print(result)

Key point: The max_iterations limit is not optional. I’ve seen agents hit 100+ calls because nobody set a ceiling. Set it to 5 by default and increase only when testing proves you need more.

Pattern 3: Hierarchical Planning (Plan → Execute Subtasks → Synthesize)

For complex workflows—analyzing a report, planning a campaign, debugging a system—break the problem into subtasks first. Have the agent plan, then execute the plan, then synthesize. This gives you visibility into what the agent thinks it needs to do before it wastes tokens doing it.

Tool Calling: Setup and Failure Modes

Tool calling in Claude (since March 2025) is reliable, but the setup matters. You define tools as JSON schemas. The model decides which tool to call and with what parameters. You execute the tool and feed results back.

Most failures come from two places:

1. Vague Tool Descriptions

Bad: "search" - search for information

Good: "search_customer_database" - search by email, name, or ID. Returns customer record with purchase history. Use this when you need to verify customer details before processing orders.

The model picks tools based on descriptions. Vague descriptions lead to wrong tool selection.

2. Missing Error Feedback

When a tool fails, tell the agent specifically why. Don’t just return a generic error. In the agentic loop code above, each tool result goes back as a message. If a search fails, say "No results found for query 'xyz'. Try a different search term." instead of "Error."

Memory: Stateless vs Persistent

Agents need to remember context. You have two options:

Conversation history (stateless): Pass the entire message thread to the model each time. Works for short interactions. Gets expensive fast. Token cost = O(conversation_length) per call.

Persistent memory: Store conversation summary, key facts, and tool execution logs in a database. Pass only relevant context. Token cost stays flat.

For production agents, use persistent memory. Store the latest 10–15 messages in thread history, plus a rolling summary. If the conversation is longer than ~20 messages, ask the model to summarize and store separately.

One Pattern to Test Today

Pick Pattern 1 (Simple Routing) and implement it for one real task in your system—customer lookup, data retrieval, anything single-step. Define 2–3 tools with specific descriptions. Run 10 test queries and check:

  • Did it pick the right tool? (If not, rewrite the description.)
  • Did it use the right parameters? (If not, your input schema is unclear.)
  • Does the output actually answer the user’s question?

Once that works, move to Pattern 2. Multi-step agents are not harder—they’re just Pattern 1 in a loop. But only add the loop when single-step isn’t enough.

Batikan
· 5 min read
Share

Stay ahead of the AI curve

Weekly digest of the most impactful AI breakthroughs, tools, and strategies.

Related Articles

Cursor vs GitHub Copilot vs Claude Code: Which Wins for Production Work
Learning Lab

Cursor vs GitHub Copilot vs Claude Code: Which Wins for Production Work

Three AI coding assistants dominate production environments. This isn't a feature list. It's a breakdown of what each actually does, where it fails, and which to use for architecture, boilerplate, and debugging.

· 10 min read
Analyze Spreadsheets With Claude and GPT-4o
Learning Lab

Analyze Spreadsheets With Claude and GPT-4o

Claude and GPT-4o can analyze your spreadsheets and CSVs, but only if you structure the data correctly and ask with precision. Learn how to upload files, write analysis prompts, and avoid hallucination pitfalls.

· 2 min read
LLM Hallucinations: Why They Happen and 5 Ways to Stop Them
Learning Lab

LLM Hallucinations: Why They Happen and 5 Ways to Stop Them

Why do language models confidently invent facts? Because they predict tokens, not truth. Learn how grounding, constraint prompting, and temperature settings cut hallucination rates from 15%+ to under 5% in production systems.

· 5 min read
Freelancer AI Workflows That Actually Increase Billable Hours
Learning Lab

Freelancer AI Workflows That Actually Increase Billable Hours

AI can double your freelance output without replacing your judgment. Learn four production workflows that compress administrative tasks and recover 10+ billable hours per month.

· 6 min read
Stop Hallucinating: How RAG Actually Grounds LLMs
Learning Lab

Stop Hallucinating: How RAG Actually Grounds LLMs

RAG grounds LLMs with your actual data, eliminating hallucinations. This guide explains how RAG works in production, why basic setups fail, and the specific patterns that work — with code examples and trade-offs.

· 6 min read
Where Your Prompts Go: Data Handling in ChatGPT, Claude, and Gemini
Learning Lab

Where Your Prompts Go: Data Handling in ChatGPT, Claude, and Gemini

ChatGPT stores your data and uses it for training by default. Claude doesn't train on web conversations unless you opt in. Gemini links your chats to your entire Google account. Here's what each model does with your prompts and how to protect sensitive information.

· 4 min read

More from Prompt & Learn

Otter vs Fireflies vs tl;dv: Meeting Transcription Shootout
AI Tools Directory

Otter vs Fireflies vs tl;dv: Meeting Transcription Shootout

Three tools promise to transcribe your meetings and extract action items. Only one integrates cleanly with your workflow. Here's the real comparison: Otter vs Fireflies vs tl;dv — accuracy data, pricing breakdowns, and honest pros/cons for each.

· 4 min read
Gamma vs Beautiful.ai vs Tome: Slide Generation Tested
AI Tools Directory

Gamma vs Beautiful.ai vs Tome: Slide Generation Tested

I tested Gamma, Beautiful.ai, and Tome on production presentations. Gamma generates fastest but struggles with branding. Beautiful.ai delivers visual consistency and data handling. Tome offers flexibility and collaboration. Here's what actually works in practice — and when each tool wins.

· 11 min read
App Store Launches Spike in 2026. AI Tooling Is the Catalyst
AI News

App Store Launches Spike in 2026. AI Tooling Is the Catalyst

Appfigures reports a measurable surge in app launches in 2026, driven by AI development tools that compress timelines from weeks to days. A solo developer with Claude or Mistral can now ship what required a full engineering team in 2022.

· 3 min read
Julius AI vs ChatGPT vs Claude for Data Analysis
AI Tools Directory

Julius AI vs ChatGPT vs Claude for Data Analysis

Julius AI, ChatGPT Advanced Data Analysis, and Claude Artifacts all handle data tasks, but execution speed, pricing, and workflow differ significantly. Here's how to pick the right one for your use case.

· 4 min read
Perplexity vs Google AI vs Consensus: Which Wins for Academic Research
AI Tools Directory

Perplexity vs Google AI vs Consensus: Which Wins for Academic Research

Perplexity, Google AI, and Consensus each excel at different research tasks. Perplexity wins on recent topics with real-time synthesis. Consensus delivers unmatched citation precision for peer-reviewed work. Google Scholar provides historical depth. This breakdown shows exactly which tool to use for your next paper—and why.

· 10 min read
Google’s Travel Tools Cut Planning Time in Half. Here’s What Actually Works
AI Tools Directory

Google’s Travel Tools Cut Planning Time in Half. Here’s What Actually Works

Google released seven integrated travel tools this spring. Price tracking predicts optimal booking windows, restaurant availability pulls real-time data, and offline maps work without cell coverage. Here's which features earn trust and where to set expectations.

· 3 min read

Stay ahead of the AI curve

Weekly digest of the most impactful AI breakthroughs, tools, and strategies. No noise, only signal.

Follow Prompt Builder Prompt Builder