How to Build an AI Agent in Python from Scratch

Build a working AI agent in pure Python. Learn the agent loop, tool calling, reasoning, and memory without relying on a heavy framework.

Khalid Abdelaty 14 min read 8 views

How to Build an AI Agent in Python from Scratch

An AI agent is a program that can reason, act, and observe in a loop. In this tutorial you will build a minimal agent in plain Python that can choose tools, run them, and answer questions.

What you will build

A Python agent that can answer questions like "What is the weather in Paris?" by deciding whether to use a weather tool or answer directly.

The agent loop

Every agent follows the same cycle:

1. Receive a task or question

2. Think about what to do

3. Act by calling a tool or generating an answer

4. Observe the result

5. Repeat until done

Set up the project

python -m venv .venv
source .venv/bin/activate
pip install openai python-dotenv

Create a .env file with your OpenAI API key:

OPENAI_API_KEY=sk-...

Define a simple tool

import json
import os
import random
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

def get_weather(city: str) -> str:
    """Return fake weather for demo purposes. Replace with a real API."""
    conditions = ["sunny", "cloudy", "rainy"]
    temp = random.randint(10, 30)
    return f"The weather in {city} is {random.choice(conditions)} and {temp}°C."

tools = {
    "get_weather": get_weather
}

Describe tools to the model

tool_definitions = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a city",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "City name"}
                },
                "required": ["city"]
            }
        }
    }
]

Run the agent loop

def run_agent(question: str, max_turns: int = 5) -> str:
    messages = [{"role": "user", "content": question}]

    for _ in range(max_turns):
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
            tools=tool_definitions
        )

        choice = response.choices[0]

        if choice.message.content:
            return choice.message.content

        if choice.message.tool_calls:
            messages.append({
                "role": "assistant",
                "content": "",
                "tool_calls": [tc.model_dump() for tc in choice.message.tool_calls]
            })
            for tc in choice.message.tool_calls:
                name = tc.function.name
                args = json.loads(tc.function.arguments)
                result = tools[name](**args)
                messages.append({
                    "role": "tool",
                    "tool_call_id": tc.id,
                    "content": result
                })

    return "I could not find an answer."

print(run_agent("What is the weather in Paris?"))

Add memory

Keep a conversation history across calls so the agent remembers context.

class Agent:
    def __init__(self):
        self.history = []

    def chat(self, message: str) -> str:
        self.history.append({"role": "user", "content": message})
        answer = run_agent_with_history(self.history)
        self.history.append({"role": "assistant", "content": answer})
        return answer

Add more tools

Good tools to add next:

  • search_web(query) using an API like Serper or Tavily
  • read_file(path) for local file access
  • send_email(to, subject, body) for automation
  • calculate(expression) for math reliability

From scratch to framework

Once you understand the loop, you can adopt LangGraph, CrewAI, or AutoGen with confidence. The concepts are the same; the frameworks just handle routing, memory, and parallelism for you.

Next steps

  • Add error handling and retries
  • Let the agent ask clarifying questions
  • Persist history to a database
  • Build a web UI with Streamlit or Gradio

Building an AI agent from scratch is the best way to understand how models, tools, and memory fit together.

Discussion

Sign in to join the discussion.

Keep learning