AI Agents: Build Your First One in 30 Minutes
An AI agent is an LLM that can use tools and make decisions in a loop. Claude Code, Devin, and Manus are all agents. This tutorial builds one from scratch.
What is an agent?
โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ
โ LLM โโโโโโบโ Action โโโโโโบโ Observe โ
โ (think) โ โ (use toolโ โ (result) โโโโ
โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โฒ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The LLM thinks โ picks a tool โ observes result โ repeats until done.
From LLM to agent
def naive_agent(user_request):
response = llm(user_request)
return response # one-shot, no tools
Thatโs just an LLM. Not an agent.
def real_agent(user_request, tools):
messages = [{"role": "user", "content": user_request}]
while True:
response = llm_with_tools(messages, tools=tools)
if response.tool_call:
result = execute_tool(response.tool_call)
messages.append({"role": "tool", "content": result})
else:
return response.content
Thatโs an agent.
Your first ReAct agent
import openai
import json
client = openai.OpenAI()
def calculator(expression: str) -> str:
return str(eval(expression)) # don't do this in prod
def search_web(query: str) -> str:
# Call your search API here
return f"Top result for {query}: ..."
tools = [
{"type": "function", "function": {
"name": "calculator",
"description": "Evaluate a math expression",
"parameters": {"type": "object", "properties": {"expression": {"type": "string"}}, "required": ["expression"]}
}},
{"type": "function", "function": {
"name": "search_web",
"description": "Search the web for current information",
"parameters": {"type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"]}
}},
]
def run_agent(user_request):
messages = [{"role": "user", "content": user_request}]
for _ in range(5): # max iterations
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools,
)
msg = response.choices[0].message
messages.append(msg)
if msg.tool_calls:
for tool in msg.tool_calls:
args = json.loads(tool.function.arguments)
result = globals()[tool.function.name](**args)
messages.append({"role": "tool", "tool_call_id": tool.id, "content": result})
else:
return msg.content
return "Max iterations reached"
print(run_agent("What's 25 * 4 and what's the weather in Tokyo?"))
Key takeaways
- Agent = LLM + tools + loop
- ReAct pattern: Reason โ Act โ Observe
- Always set max iterations (avoid infinite loops)