Skip to main content
Build a real AI agent from scratch with plain Python and OpenRouter. This no-framework beginner's guide reveals exactly how tool calling and reasoning loops work under the hood.

Master AI Agents from Scratch: The Ultimate No-Framework Beginner's Guide

By Muhammad Hassan Ali 5 min read
Guide
AI Agents OpenRouter Python LLM ReAct BeginnerGuide

I recently received an email from a reader who said something that really stuck with me:

“I see AI agents everywhere on YouTube and Medium, but every tutorial makes them feel so overwhelmingly complex. LangChain, vector databases, multi-agent frameworks, complex async orchestration… as a complete beginner, I just can’t wrap my head around where to start. Is there an actual simple way to build one?”

If you have felt that exact same frustration, this guide is for you.

The truth is, most AI agent tutorials overcomplicate the core concept. At its heart, an AI agent is not magic. It is simply an LLM placed inside a loop that can think, pick a tool to run, inspect the output, and give you a final answer.

In this beginner guide, we are stripping away all the noise. We will not be using heavy frameworks. Instead, we are building a straightforward Weather Agent from scratch using Python and the OpenRouter API. By the end of this tutorial, you will fully understand how tool calling and reasoning loops work.

Before we dive in, I want to say a huge thank you to everyone who reaches out to me via email and LinkedIn. I read every single message. As a human content creator, I run out of ideas too, and your real-world questions are what fuel articles like this one. Please keep sending your feedback, questions, and topic suggestions. Your support is what keeps me moving forward.

What Is an AI Agent? (In Plain English)

A normal LLM (like basic ChatGPT) only knows what was in its training data or what you paste into the chat. If you ask it “What is the weather in Tokyo right now?”, it will tell you it does not have live internet access.

An AI Agent solves this by giving the LLM a “toolbox”.

When you ask an agent a question:

  1. Thought: The LLM looks at your question and checks its toolbox. It says: “I don’t know the live weather, but I have a get_weather function.”
  2. Action: The agent executes that Python function.
  3. Observation: The function returns live data (for example, 22°C, Sunny) back to the LLM.
  4. Final Answer: The LLM uses that result to write a friendly final answer to you.

Step 1: Get Your Free OpenRouter Key and Setup

OpenRouter gives you a single API key to access over 400+ models (OpenAI, Claude, Gemini, Llama, DeepSeek) using the exact same code.

Grab an API key at openrouter.ai.

Install the standard OpenAI Python package (OpenRouter uses the same format):

pip install openai python-dotenv

Create a .env file in your code folder:

OPENROUTER_API_KEY=your_openrouter_api_key_here

Step 2: Write Your First Weather Tool

Let us write a simple Python function that simulates checking the weather for a city:

import os
import json
from openai import OpenAI
from dotenv import load_dotenv

# Load API Key
load_dotenv()

# 1. Define the Python tool function
def get_weather(location: str) -> str:
    """Mock weather service returning live-style weather string."""
    weather_database = {
        "tokyo": "22°C, Sunny with a light breeze",
        "london": "14°C, Rain and overcast",
        "karachi": "32°C, Humid and partly cloudy",
        "new york": "19°C, Clear skies"
    }
    clean_city = location.lower().strip()
    return weather_database.get(clean_city, f"25°C, Pleasant weather in {location}")

# Map function name to actual executable function
AVAILABLE_TOOLS = {
    "get_weather": get_weather
}

Step 3: Tell the AI About Your Tool (JSON Schema)

We describe our function to the LLM so it knows when and how to call it:

tools_schema = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Fetches current weather for a specified city.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city name, e.g., Tokyo or London"
                    }
                },
                "required": ["location"]
            }
        }
    }
]

Step 4: The Core Agent Loop

Here is the entire agent loop in clean, easy-to-understand Python:

# Initialize OpenRouter Client
client = OpenAI(
    base_url="https://openrouter.ai/api/v1", # Point to OpenRouter
    api_key=os.getenv("OPENROUTER_API_KEY")
)

def run_weather_agent(user_question: str):
    messages = [
        {"role": "system", "content": "You are a helpful AI Weather Assistant. Use your weather tool when asked about climate or temperature in cities."},
        {"role": "user", "content": user_question}
    ]

    print(f"👤 User Question: {user_question}")

    # Run loop up to 3 turns
    for turn in range(3):
        # Call the LLM (using openai/gpt-oss-20b:free or any model you prefer)
        response = client.chat.completions.create(
            model="openai/gpt-oss-20b:free", 
            messages=messages,
            tools=tools_schema,
            tool_choice="auto"
        )

        response_message = response.choices[0].message
        messages.append(response_message)

        # Check if the AI decided to call our tool
        if response_message.tool_calls:
            for tool_call in response_message.tool_calls:
                fn_name = tool_call.function.name
                fn_args = json.loads(tool_call.function.arguments)

                print(f"🤖 Agent Thought: I need to call function '{fn_name}' with args {fn_args}")

                # Execute our local Python weather tool
                if fn_name in AVAILABLE_TOOLS:
                    result = AVAILABLE_TOOLS[fn_name](**fn_args)
                    print(f"⚙️ Tool Output: {result}")

                    # Feed the weather data back to the AI
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "name": fn_name,
                        "content": str(result)
                    })
        else:
            # If no tool call was needed, the agent gives its final response
            print("\n✅ Final Agent Answer:")
            print(response_message.content)
            return response_message.content

# Run the agent
if __name__ == "__main__":
    run_weather_agent("What is the weather like in Tokyo right now, and what should I wear?")

Output Trace

When you run this script, here is what happens step-by-step:

👤 User Question: What is the weather like in Tokyo right now, and what should I wear?
🤖 Agent Thought: I need to call function 'get_weather' with args {'location': 'Tokyo'}
⚙️ Tool Output: 22°C, Sunny with a light breeze

✅ Final Agent Answer:
It is currently 22°C and sunny with a light breeze in Tokyo. A comfortable t-shirt with a light jacket or cardigan for the breeze would be ideal to wear!

That is all there is to it! You built a fully functional ReAct AI Agent without any confusing third-party agent frameworks.

Found this valuable? Share the insight.

Related Articles

Stop wasting money on the newest LLM. Learn why prompt technique matters more than model version, and how to get flagship results at a fraction of the cost.

The Chasing-Model Trap: Why Upgrading Your LLM Won't Fix Bad Prompting
Analysis

Stop wasting money on the newest LLM. Learn why prompt technique matters more than model version, and how to get flagship results at a fraction of the cost.

I tested the top 5 multi-agent AI platforms for 2026. Here is my breakdown of AutoGen, CrewAI, AirgapAI, Sema4.ai, and LangGraph for enterprise workflows.

Top 5 Multi-Agent AI Platforms for Enterprise Workflows in 2026
Review

I tested the top 5 multi-agent AI platforms for 2026. Here is my breakdown of AutoGen, CrewAI, AirgapAI, Sema4.ai, and LangGraph for enterprise workflows.

A no-fluff, battle-tested breakdown of how to build an AI trading bot in Python — covering strategy, data, model selection, backtesting, and the real reasons most bots blow up.

I Built My Own AI Trading Bot. Here's the Brutally Honest Guide to Doing It Yourself
Tutorial

A no-fluff, battle-tested breakdown of how to build an AI trading bot in Python — covering strategy, data, model selection, backtesting, and the real reasons most bots blow up.

Learn how LiteLLM unifies 100+ LLMs (OpenAI, Anthropic, Gemini, Groq) behind one AI gateway, cuts provider lock-in, and gives teams full control, observability, and cost tracking.

LiteLLM: The Ultimate Open-Source AI Gateway for 100+ LLMs
Guide

Learn how LiteLLM unifies 100+ LLMs (OpenAI, Anthropic, Gemini, Groq) behind one AI gateway, cuts provider lock-in, and gives teams full control, observability, and cost tracking.