# Why do we import 100MB of frameworks to run a 50-line LLM reasoning loop?

> Source: <https://dev.to/venu_varma/why-do-we-import-100mb-of-frameworks-to-run-a-50-line-llm-reasoning-loop-3afh>
> Published: 2026-06-25 15:31:08+00:00

Stop Importing Bloated Frameworks: Build a Python AI Agent from Scratch

You want to build an AI agent.

So you head to the docs of a popular orchestration framework, copy the boilerplate, import 20 modules, and spin up an agent. It works—until it doesn't.

Suddenly, you're looking at a 50-line stack trace originating from a library wrapper. You don't know where the query failed, what the exact prompt was, or why the tool call failed to parse.

Here is the truth: **You don't need AutoGen, LangChain, or CrewAI to build a working AI agent.**

You just need vanilla Python and a basic understanding of the three core pillars of agentic design.

**The Three Pillars of an AI Agent**

Any basic agent can be broken down into three simple components:

`role`

and `content`

) passed to and from the LLM.`while`

loop that calls the LLM, checks if it wants to use a tool, runs the tool if requested, appends the result to the State, and repeats until the LLM returns a final answer.Let’s build one.

This example uses the official `openai`

SDK, but the same logic applies to Anthropic, Gemini, or local models running via Ollama.

``` python
python
import os
import json
from openai import OpenAI

# Initialize client
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

# 1. Define the tools our agent can use
def get_weather(location):
    if "tokyo" in location.lower():
        return "Tokyo is sunny and 25°C."
    return "Cool and rainy, 15°C."

# Map the function name to the actual function object
tools_map = {
    "get_weather": get_weather
}

# Define the JSON schema so the LLM knows how to call it
tool_definition = {
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {"type": "string"}
            },
            "required": ["location"]
        }
    }
}

# 2. The Agent reasoning loop
def run_agent(user_prompt):
    # Initialize the State (Memory)
    messages = [
        {"role": "system", "content": "You are a helpful assistant. Call tools when necessary."},
        {"role": "user", "content": user_prompt}
    ]

    # Run the loop (max 5 turns to prevent infinite runs)
    for _ in range(5):
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
            tools=[tool_definition]
        )

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

        # Check if the model wants to call a tool
        if message.tool_calls:
            for tool_call in message.tool_calls:
                name = tool_call.function.name
                args = json.loads(tool_call.function.arguments)

                print(f"[*] Calling tool: {name} with args: {args}")
                tool_output = tools_map[name](**args)

                # Append tool response back to state
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "name": name,
                    "content": tool_output
                })
        else:
            # If no tool was called, this is the final answer
            return message.content

# Run it
if __name__ == "__main__":
    result = run_agent("What is the weather like in Tokyo right now?")
    print(f"\n[Agent Response]: {result}")
```


