Building Your First AI Agent: A Practical Step-by-Step Guide
Enough theory — let’s build something. In this guide, we’ll create a working AI agent from scratch that can reason, use tools, and complete multi-step tasks.
What We’re Building
By the end of this tutorial, you’ll have an agent that can:
- Accept a natural language goal
- Break it into steps
- Use tools (web search, calculator) to gather information
- Synthesize a final answer
We’re using Python and LangGraph because it gives you the most control over agent behavior while keeping the code clean.
Prerequisites
- Python 3.10+
- An API key from Anthropic (Claude) or OpenAI
- Basic familiarity with Python
Step 1: Set Up Your Environment
pip install langgraph langchain-anthropic langchain-community tavily-python
Create a .env file:
ANTHROPIC_API_KEY=your-key-here
TAVILY_API_KEY=your-key-here
Step 2: Define Your Tools
Tools are functions your agent can call. Let’s start with two simple ones:
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.tools import tool
search = TavilySearchResults(max_results=3)
@tool
def calculator(expression: str) -> str:
"""Evaluate a mathematical expression."""
try:
result = eval(expression) # In production, use a safe parser
return str(result)
except Exception as e:
return f"Error: {e}"
tools = [search, calculator]
Step 3: Create the Agent Graph
This is where LangGraph shines. We define the agent as a graph of nodes:
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(model="claude-sonnet-4-5-20250929", temperature=0)
agent = create_react_agent(model, tools)
Step 4: Run Your Agent
result = agent.invoke({
"messages": [
{"role": "user", "content": "What's the population of Tokyo and what's that number divided by 7?"}
]
})
for message in result["messages"]:
print(f"{message.type}: {message.content}")
Your agent will:
- Search for Tokyo’s population
- Extract the number
- Use the calculator to divide by 7
- Return a synthesized answer
Step 5: Add Memory
To make the agent remember previous interactions:
from langgraph.checkpoint.memory import MemorySaver
memory = MemorySaver()
agent = create_react_agent(model, tools, checkpointer=memory)
config = {"configurable": {"thread_id": "session-1"}}
result = agent.invoke(
{"messages": [{"role": "user", "content": "What's the capital of France?"}]},
config
)
Now your agent maintains conversation history across invocations.
What Just Happened?
Let’s break down the agent’s decision loop:
- Receive the user’s goal
- Reason about what information is needed (this is the “Re” in ReAct)
- Act by calling a tool
- Observe the tool’s output
- Repeat steps 2-4 until the goal is met
- Respond with the final answer
This ReAct (Reason + Act) pattern is the foundation of most production agents today.
Common Pitfalls
- Don’t give agents too many tools — Start with 2-3. More tools = more confusion for the model.
- Be specific in tool descriptions — The model decides which tool to use based on the description string.
- Set temperature to 0 for agents — You want deterministic, reliable behavior, not creativity.
- Add timeout and retry logic — Tool calls fail. Plan for it.
Next Steps
Now that you have a basic agent, you can:
- Add more tools (file reading, API calls, code execution)
- Implement a plan-and-execute pattern for complex tasks
- Build a multi-agent system with specialized roles
- Add evaluation and testing
I’ll cover each of these in upcoming articles.
This is part of the Build an Agent series. Check out What Is Agentic AI? if you want the fundamentals first.