Skip to main content

Agent Architecture — ReAct, Tool Use, and Reasoning Loops

33/40
Chapter 9 Build Autonomous Multi-Agent Systems

Agent Architecture — ReAct, Tool Use, and Reasoning Loops

28 min read Lesson 33 / 40 Preview

From Chatbots to Autonomous Agents

An LLM chatbot responds to a single prompt. An agent reasons, plans, uses tools, and takes actions in a loop until the task is done. This is the most transformative pattern in AI engineering.

What Makes an Agent?

Chatbot:  User → LLM → Response (one-shot)

Agent:    User → LLM → Think → Act → Observe → Think → Act → ... → Final Answer
                        └─── uses tools: search, code, APIs, databases ───┘

The ReAct Pattern (Reasoning + Acting)

Thought: I need to find the current stock price of Apple.
Action: search("AAPL stock price today")
Observation: AAPL is trading at $198.50, up 2.3% today.
Thought: Now I need to calculate the market cap.
Action: calculator("198.50 * 15400000000")
Observation: 3,056,900,000,000
Thought: I have all the information needed.
Answer: Apple (AAPL) is trading at $198.50 with a market cap of ~$3.06 trillion.

Building a ReAct Agent from Scratch

from openai import OpenAI
import json, re

client = OpenAI()

# Define tools the agent can use
TOOLS = {
    "search": lambda q: f"Search results for '{q}': [simulated results]",
    "calculator": lambda expr: str(eval(expr)),
    "get_weather": lambda city: f"Weather in {city}: 72F, sunny",
}

TOOL_DESCRIPTIONS = """
Available tools:
- search(query): Search the web for information
- calculator(expression): Evaluate a math expression
- get_weather(city): Get current weather for a city
"""

def react_agent(question, max_steps=5):
    """ReAct agent that reasons and acts in a loop."""
    messages = [
        {"role": "system", "content": f"""You are a helpful agent that solves problems step by step.

{TOOL_DESCRIPTIONS}

Follow this format EXACTLY:
Thought: <your reasoning>
Action: <tool_name>(<argument>)

OR when you have the final answer:
Thought: <your reasoning>
Answer: <your final answer>"""},
        {"role": "user", "content": question}
    ]

    for step in range(max_steps):
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            temperature=0
        )
        output = response.choices[0].message.content
        print(f"Step {step + 1}:\n{output}\n")

        # Check if we have a final answer
        if "Answer:" in output:
            answer = output.split("Answer:")[-1].strip()
            return answer

        # Extract and execute action
        action_match = re.search(r"Action:\s*(\w+)\((.+?)\)", output)
        if action_match:
            tool_name = action_match.group(1)
            tool_arg = action_match.group(2).strip("\"' ")

            if tool_name in TOOLS:
                observation = TOOLS[tool_name](tool_arg)
                messages.append({"role": "assistant", "content": output})
                messages.append({"role": "user",
                    "content": f"Observation: {observation}"})
            else:
                messages.append({"role": "assistant", "content": output})
                messages.append({"role": "user",
                    "content": f"Observation: Unknown tool '{tool_name}'"})
        else:
            break

    return "Agent could not find an answer within the step limit."

# Test the agent
answer = react_agent("What is the weather in Tokyo and what is 72F in Celsius?")
print(f"Final: {answer}")

Function Calling with OpenAI

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_database",
            "description": "Search the product database",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "Search query"},
                    "category": {"type": "string", "enum": ["electronics", "clothing", "books"]},
                    "max_price": {"type": "number", "description": "Maximum price filter"}
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "place_order",
            "description": "Place an order for a product",
            "parameters": {
                "type": "object",
                "properties": {
                    "product_id": {"type": "string"},
                    "quantity": {"type": "integer", "minimum": 1}
                },
                "required": ["product_id", "quantity"]
            }
        }
    }
]

def run_agent_with_tools(user_message):
    messages = [{"role": "user", "content": user_message}]

    while True:
        response = client.chat.completions.create(
            model="gpt-4o", messages=messages, tools=tools)

        message = response.choices[0].message

        if message.tool_calls:
            messages.append(message)
            for call in message.tool_calls:
                fn_name = call.function.name
                fn_args = json.loads(call.function.arguments)
                result = execute_function(fn_name, fn_args)
                messages.append({
                    "role": "tool",
                    "tool_call_id": call.id,
                    "content": json.dumps(result)
                })
        else:
            return message.content

def execute_function(name, args):
    """Execute a tool function and return results."""
    if name == "search_database":
        return {"products": [{"id": "P001", "name": "Laptop", "price": 999}]}
    elif name == "place_order":
        return {"order_id": "ORD-789", "status": "confirmed"}
    return {"error": "Unknown function"}

answer = run_agent_with_tools(
    "Find me a laptop under $1000 and order the best one")
print(answer)

Agent Design Patterns

Pattern Use Case Complexity
ReAct General problem solving Medium
Plan-and-Execute Multi-step tasks High
Reflexion Self-improving agents High
Tool-only API orchestration Low
Chain-of-Thought Reasoning tasks Low

Key Takeaway

Agents extend LLMs from text generators to autonomous problem solvers. The ReAct pattern (think → act → observe → repeat) is the foundation of all agent architectures. Master tool integration and you can build agents that accomplish real-world tasks.