{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreigbpuu45mpc4hnzc2u67hiebijc4bspelbb7gpe54nk3w53jguuwa",
"uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mp4ruxwu3o62"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreig3jroko6w5xqo3af7qkz6x4un2feo2kpbjxcz36jpnsq66hfdja4"
},
"mimeType": "image/webp",
"size": 79518
},
"path": "/venu_varma/why-do-we-import-100mb-of-frameworks-to-run-a-50-line-llm-reasoning-loop-3afh",
"publishedAt": "2026-06-25T15:31:08.000Z",
"site": "https://dev.to",
"tags": [
"agents",
"ai",
"llm",
"python"
],
"textContent": "Stop Importing Bloated Frameworks: Build a Python AI Agent from Scratch\n\nYou want to build an AI agent.\n\nSo 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.\n\nSuddenly, 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.\n\nHere is the truth: **You don't need AutoGen, LangChain, or CrewAI to build a working AI agent.**\n\nYou just need vanilla Python and a basic understanding of the three core pillars of agentic design.\n\n**The Three Pillars of an AI Agent**\n\nAny basic agent can be broken down into three simple components:\n\n 1. **The State (Memory):** A list of message dictionaries (`role` and `content`) passed to and from the LLM.\n 2. **The Schema (Tools):** A dictionary mapping tool names to standard Python functions.\n 3. **The Loop (Reasoning):** A standard `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.\n\n\n\nLet’s build one.\n\n## Coding the Agent (under 60 lines of Python)\n\nThis example uses the official `openai` SDK, but the same logic applies to Anthropic, Gemini, or local models running via Ollama.\n\n\n python\n import os\n import json\n from openai import OpenAI\n\n # Initialize client\n client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\"))\n\n # 1. Define the tools our agent can use\n def get_weather(location):\n if \"tokyo\" in location.lower():\n return \"Tokyo is sunny and 25°C.\"\n return \"Cool and rainy, 15°C.\"\n\n # Map the function name to the actual function object\n tools_map = {\n \"get_weather\": get_weather\n }\n\n # Define the JSON schema so the LLM knows how to call it\n tool_definition = {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_weather\",\n \"description\": \"Get the current weather for a location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"location\": {\"type\": \"string\"}\n },\n \"required\": [\"location\"]\n }\n }\n }\n\n # 2. The Agent reasoning loop\n def run_agent(user_prompt):\n # Initialize the State (Memory)\n messages = [\n {\"role\": \"system\", \"content\": \"You are a helpful assistant. Call tools when necessary.\"},\n {\"role\": \"user\", \"content\": user_prompt}\n ]\n\n # Run the loop (max 5 turns to prevent infinite runs)\n for _ in range(5):\n response = client.chat.completions.create(\n model=\"gpt-4o-mini\",\n messages=messages,\n tools=[tool_definition]\n )\n\n message = response.choices[0].message\n messages.append(message)\n\n # Check if the model wants to call a tool\n if message.tool_calls:\n for tool_call in message.tool_calls:\n name = tool_call.function.name\n args = json.loads(tool_call.function.arguments)\n\n print(f\"[*] Calling tool: {name} with args: {args}\")\n tool_output = tools_map[name](**args)\n\n # Append tool response back to state\n messages.append({\n \"role\": \"tool\",\n \"tool_call_id\": tool_call.id,\n \"name\": name,\n \"content\": tool_output\n })\n else:\n # If no tool was called, this is the final answer\n return message.content\n\n # Run it\n if __name__ == \"__main__\":\n result = run_agent(\"What is the weather like in Tokyo right now?\")\n print(f\"\\n[Agent Response]: {result}\")\n\n\n",
"title": "Why do we import 100MB of frameworks to run a 50-line LLM reasoning loop?"
}