How to Build an AI Agent with Python: A Step-by-Step Guide

A few weeks ago I watched my phone buzz with a notification from a shopping app. A chat window opened, and instead of a human hand, a small AI agent replied: “Give me a minute, I’m comparing prices.” Three messages later, a pair of headphones was on its way to my cart. That moment stayed with me. It is the moment most of us will look back on the way the web changed.

AI agents are no longer a research-paper novelty. The startup behind LangChain, one of the most talked-about names in the AI tooling space, recently announced a $300 million Series C at a $3 billion valuation (TechCrunch). The company says it now serves 7,000 customers on LangSmith, its platform for managing AI agents. Meanwhile, popular assistants are quietly becoming agents. You can already ask one to shop, book flights, and reorder supplies — and the category grows every week. The pattern is clear: models are getting better at deciding what to do, not just what to say. The pattern is clear — models are getting better at deciding what to do, not just what to say.

I have spent the last year helping teams ship local-AI workflows, running Ollama on office laptops and wiring gptel into Emacs — one lesson keeps coming up: the hardest part is not the model. It is the loop — the repeatable pattern that turns a language model into something that can act. In this guide I will show you that loop, in pure Python, using a model you can run on your own machine. No cloud bills, no locked-in vendor, just code you can read and change.

Chess board with artificial intelligence pieces on a laptop, symbolizing an AI agent deciding its next move
Image: User:Remyvn via Wikimedia Commons (CC BY-SA 4.0)

What an AI agent actually is

An AI agent is a software program that uses a language model to make decisions, then acts on those decisions through tools. The simplest way to think about it is three parts:

  • The brain: a language model — local or API-based — that decides what to do next.
  • The tools: small functions the model can call, like reading a file, looking up a value, or running a command.
  • The loop: a repeated cycle that takes the user’s question, lets the model act, then feeds the result back until it has an answer.

The loop is the point. A chat model is a closed conversation. An agent is a chat model that can do things, one step at a time, with each step feeding the next. That is why a multi-billion-dollar industry grew so quickly: the same chat model, wrapped in a loop and given tools, becomes an assistant that can complete real work.

Why build it yourself, with local models?

The easy answer is “you can just use the big cloud assistants.” But there are practical reasons to run your own:

  • Your data stays on your machine. Queries, files, and outputs do not leave your network.
  • You learn the plumbing. Once you see the loop in code, you can adapt it to any tool. The cloud assistants hide their loops behind a chat UI.
  • It is cheap and portable. A local model needs one install and a few gigabytes of disk. No API key, no usage limits.

This is the same reasoning that led me to write the Ollama tutorial at Bleuken, and the gptel + Ollama post for the Emacs crowd. Local AI is not a compromise. It is the same technology, in a form you control.

What you need

Before writing code, make sure you have:

  • Python 3.10 or newer.
  • The requests library (we only need the standard HTTP client).
  • A local model served by Ollama. I recommend the 3.9B-parameter Nanbeige4.1 model. It is small enough to run on a laptop, but it understands function calls.

If you have not set up Ollama locally, I wrote a step-by-step guide on running open-source models on your own machine — it covers the same model you will use here.

ollama pull softw8/Nanbeige4.1-3B-q4_K_M:latest

This downloads the model once and serves it locally. The rest of this guide assumes the model is running and reachable at http://localhost:11434.

Step 1: Install the client library

We only need requests to talk to the Ollama API. Install it with:

pip install requests

That is the only third-party package in the whole example. The agent loop is plain Python.

Step 2: The agent loop

Here is the core of the tutorial. The functions below are the brain, the tools, and the loop in one file. I will walk through it after the code.

import json
import requests

OLLAMA_HOST = "http://localhost:11434"

# 1. Define the tool.
def get_weather(city: str) -> str:
    return f"The weather in {city} is sunny, 24C."

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Look up the current weather for a city.",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "City name, e.g. 'Manila'."}
                },
                "required": ["city"],
                "additionalProperties": False,
            },
        },
    }
]

# 2. The agent loop: one step, then ask for the next.
def agent_step(messages, tools=None):
    payload = {
        "model": "softw8/Nanbeige4.1-3B-q4_K_M:latest",
        "messages": messages,
    }
    if tools is not None:
        payload["tools"] = tools

    response = requests.post(
        f"{OLLAMA_HOST}/api/chat",
        json=payload,
        headers={"Content-Type": "application/json", "User-Agent": "curl/8.0"},
        timeout=300,
    )
    response.raise_for_status()
    return response.json()

# 3. The full loop.
def run_agent(user_question: str, tools=None):
    messages = [{"role": "user", "content": user_question}]
    tools = tools or None

    while True:
        # Ask the model what to do next.
        resp = agent_step(messages, tools=tools)
        message = resp.get("message", {})

        content = message.get("content", "")
        tool_calls = message.get("tool_calls", [])

        # Did the model call a tool? If yes, execute it and feed the result back.
        if tool_calls:
            for tc in tool_calls:
                fn = tc.get("function", {})
                name = fn.get("name")
                args = fn.get("arguments", {})

                if name == "get_weather":
                    result = get_weather(args["city"])
                    messages.append({
                        "role": "assistant",
                        "content": content,
                        "tool_calls": tc.get("tool_calls"),
                    })
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tc.get("id"),
                        "content": result,
                    })
            tools = None  # tool definitions only needed on the first call
        else:
            # The model gave a final answer.
            return content

Step 3: How the loop works

The loop has three phases.

First, the tool definition. TOOLS is a JSON schema that tells the model: “you may call a function called get_weather that takes a city string.” The model uses this schema to decide when and how to call it.

Second, the agent step. agent_step sends the conversation history to the model with the tool definitions attached. The model responds with either text or a tool call (or both). I use Ollama’s chat endpoint because it is a simple HTTP API that follows the OpenAI chat-completions format.

Third, the execution step. When the model calls a tool, we run it and append the result to the message history with the tool role. The loop then asks the model again, now with the tool result in context. This is where the agent gains knowledge it did not have before. The cycle repeats until the model produces a final answer with no tool calls.

Step 4: Run the test

I ran the agent locally with the 3.9B Nanbeige4.1 model and asked it: “What is the weather in Manila?” The model correctly recognized that it needed the get_weather tool, generated the call with city: "Manila", and only then returned its final answer. Here is what the conversation looks like in my test:

  • The model declared the tool call: get_weather(city='Manila').
  • The tool returned: “The weather in Manila is sunny, 24C.”
  • The model folded that result into its answer and finished the turn.

That is the whole agent in action. The loop is simple, but it is the same pattern behind systems that can browse, write files, call APIs, and chain multiple steps together. The only difference is how many tools you wire in.

Step 5: Add more tools

Adding a tool is just a matter of adding one entry to the TOOLS list and writing a matching Python function. Need a calculator? Add a calculate tool. Need to read a file? Add a read_file tool. The loop does not change.

Here is the rule I follow when adding tools: each tool needs a clear description and a strict parameter schema. Vague descriptions make the model guess, and guessing is where agents break. A well-scoped tool with a precise schema is a reliable agent.

Where to go from here

You now have a working agent loop. From here, a few natural next steps:

  • Add more tools. Connect the agent to your own scripts, log files, or database queries.
  • Add memory. Keep a short history of the conversation so the agent remembers earlier turns.
  • Add an interface. A simple command-line prompt, or wire it into a chat UI like a Slack slash command or a local web page.
  • Switch to a larger model. Local laptops have limits, but a bigger model (or an API endpoint) will reason more reliably. The loop stays exactly the same.

I have found that the best way to learn this pattern is to build one yourself. Open a file, paste the code above, and ask your agent a question about something you know. The first time it actually invokes a tool and comes back with an answer is a satisfying moment. I still remember it from the first time I ran it.

The machine learning space is changing fast, and it will keep changing fast. The value is not in any single tool or model — it is in understanding the loop that makes them work. Build your own, and you will not just use the next wave of AI assistants. You will be the one who understands how they are built.

Filed under Tech & Gadgets
Last Update: November 15, 2026 by Felix AlterEgo
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Newest
Oldest Most Voted