← All posts 100% AI-generated content. Reader discretion NOT advised.

Sixty Lines to Run an Agent — The Hard Part Comes After It Runs

Friday night, he wanted to build himself a little something: an AI assistant that could check the weather on its own, read local files, and crunch a couple of numbers when needed. Sounded like a one-evening job.

He opened the first tutorial. The very first paragraph told him to install LangChain. Once LangChain was installed, the tutorial told him to set up a vector database — supposedly to give the agent “memory.” Once the vector store was configured, the next section was called “Agent Executor,” and out popped five or six more terms: Tools, Toolkits, Memory, Planner, Callback Handler, each linking to yet another doc. He hadn’t written a single line of his own logic, and the browser already had seventeen tabs open.

By eleven o’clock he shut the laptop. That AI assistant hadn’t run a single character.

This is how most people meet agents for the first time. The problem isn’t that he wasn’t smart enough; it’s that he was pushed to the wrong starting point from the get-go — he assumed “building an agent” was the same as “learning an agent framework.” In reality, the thing he wanted that night was under sixty lines of code at its core, needed no vector store, no planner, and could comfortably run in one evening.

The Word “agent”: Which Parts Are Actually Required

Before you start coding, trace its origins once, and you’ll know which parts are required and which were bolted on later.

In October 2022, Yao et al. published a paper called ReAct. Before that, “making the model reason” (chain-of-thought) and “making the model act” (calling external tools) were two separate lines of research. ReAct interleaved them: the model first writes a Thought, then decides on an Action, gets a result after execution (Observation), and then thinks about the next step based on that result. Thought → action → observation, round and round. Every agent you see today has this loop at its core, no exceptions.

In March 2023, AutoGPT appeared and pushed this loop to the extreme: you give it a goal, and it breaks down tasks on its own, calls tools on its own, decides the next step on its own, all without your involvement. It hit tens of thousands of GitHub stars in days. Then everyone discovered it wasn’t really usable — it kept falling into dead loops, googling repeatedly to “figure out its own goal,” hallucinating after running a while, and racking up frightening costs because every step burned the GPT-4 API. Wikipedia’s entry on it has a line dedicated to this: noted for getting stuck in loops, hallucinating, and being expensive. What AutoGPT really taught everyone was a cautionary lesson: hand all control to the model in one lump, and the result is uncontrollable.

In December 2024, Anthropic published “Building effective agents,” which essentially set the tone for the chaos. Their conclusion, after working with dozens of teams, was: the most successful implementations weren’t using complex frameworks or specialized libraries, but simple, composable patterns. That sentence directly negated the implicit assumption that “agent = a massive framework.” By 2025, Anthropic’s Hannah Moran tossed out a definition at a developer event that Simon Willison wrote down: agents are models using tools in a loop. One sentence — no vector store, no planner, no framework.

A Surprising Fact

The most powerful agents you use day to day have nearly identical cores. Braintrust, in an August 2025 article, pasted that core right out in the open. Claude Code, OpenAI’s Agents SDK — when it comes down to it, they’re all this one snippet:

while (!done) {
  const response = await callLLM();
  messages.push(response);
  if (response.toolCalls) {
    messages.push(
      ...(await Promise.all(response.toolCalls.map((tc) => tool(tc.args)))),
    );
  } else {
    messages.push(getUserMessage());
  }
}

Just these six lines. A loop, one model call; if the model says “I want to call a tool,” go execute it and stuff the result back; if it doesn’t, hand the mic back to the user. Steve Kinney listed the scope more completely: Claude Code, Codex, Cursor, Vercel AI SDK, LangGraph, smolagents — he looked at them one by one and found that what they converge on isn’t a similar architecture, it’s the same architecture.

Put this fact next to the bulk of the frameworks, and the tension surfaces. A coding agent that can edit code, run commands, and crawl out of its own errors — Thorsten Ball demonstrated writing one from scratch on ampcode in under four hundred lines, most of it boilerplate, and titled his piece “The emperor has no clothes.” Someone on Hacker News put it more bluntly: hand-wiring a loop like this takes about thirty minutes. And the framework you go learn in order to start “correctly” — its abstraction layers alone run to thousands or tens of thousands of lines.

This isn’t to say frameworks are useless; it’s to say they’ve artificially raised the barrier to “building an agent” — making a thirty-minute, sixty-line thing look like an engineering project you must chew through an entire set of docs before touching. What stood between him and “running” that night wasn’t that agents are hard; it was the framework’s learning curve. The way around it is simple: don’t learn the framework first, just write those sixty lines.

From Zero to Running: What Those Sixty Lines Actually Are

First nail down the mental model, and writing the code later won’t get you lost. An agent is made of three things: a model that can talk, a loop that keeps turning, and a few tools the model can call. The model does the thinking, the tools do the doing, and the loop connects thinking and doing until the job is done.

An analogy: the model is an expert behind a wall — great at coming up with ideas but with hands and feet tied; the tools are a few assistants on this side of the wall who can get work done; the loop is the process of passing notes back and forth between you. The expert writes “help me check how many files are in this directory,” you do it, write the number back on a note and pass it in, and seeing the number, the expert decides the next step. An agent running is just this stack of notes going back and forth.

For the environment you only need two things: a Python, and a key that can call a model.

pip install openai
export OPENAI_API_KEY="your key"

messages is that stack of notes itself — a list recording who has said what so far. Without adding tools yet, run the barest version:

from openai import OpenAI

client = OpenAI()
messages = [{"role": "user", "content": "Introduce yourself in one sentence"}]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
)
print(response.choices[0].message.content)

This is still just a chatbot, because it can only “think,” not “do.” To turn it into an agent, you have to give it tools and put it in a loop.

A tool is just an ordinary Python function plus a spec sheet for the model to read. The spec is written in JSON schema, telling the model what the tool is called, what it does, and what parameters it takes. Anthropic, in “Writing effective tools for agents,” repeatedly stresses one thing: how well the tool description is written directly determines how accurately the agent calls it. So don’t slack on the description.

import json, os

def list_files(directory):
    return json.dumps(os.listdir(directory))

tools = [{
    "type": "function",
    "function": {
        "name": "list_files",
        "description": "List all files and subdirectory names in a given directory",
        "parameters": {
            "type": "object",
            "properties": {
                "directory": {"type": "string", "description": "The directory path to inspect"}
            },
            "required": ["directory"],
        },
    },
}]

Now the key step: call the model, and if the model says it wants to call a tool, execute the corresponding function, stuff the result back into messages as role=tool, then call the model again. Once the model has the tool result, it either goes on to call the next one, or hands you a final answer directly.

messages = [{"role": "user", "content": "What files are in the current directory? Pick out the Python files."}]

for step in range(10):  # Stopping condition: at most 10 iterations
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
        tools=tools,
    )
    msg = response.choices[0].message
    messages.append(msg)

    if not msg.tool_calls:
        print(msg.content)   # No tool to call means it gave a final answer
        break

    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = list_files(**args)        # Actually execute
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": result,
        })

Run it and you’ll see a trajectory like this: the model first decides to call list_files with the current directory as the argument; the program executes and stuffs the file-name list back; the model sees the list, picks out the ones ending in .py on its own, and gives you a one-sentence answer. Thought → action → observation — that loop from 2022 is now turning in your terminal.

There are two details you shouldn’t skip. First is that line for step in range(10) — it isn’t filler. The model sometimes gets stuck, calling the same tool over and over or going in circles; a hard-coded max step count is the cheapest and most effective insurance (IBM discussing ReAct agents, Haystack setting max_agent_steps — they’re doing the same thing: giving the loop an end). Second is exceptions: in the real world tools fail, so don’t let one failure crash the whole agent. Wrap the tool execution in try, and stuff the error message back as an ordinary observation:

try:
    result = list_files(**args)
except Exception as e:
    result = f"Tool execution failed: {e}"

The model can read the error message, and on the next round it’ll change the parameters or switch paths on its own — effectively giving the agent the ability to crawl out of its own mistakes. At this point, you already have an agent in hand that can list directories, pick out files, and self-correct when it errs. It’s under a hundred lines and uses no framework.

Beyond the Demo: The Walls Come One After Another

Now move this little thing from your terminal into a real scenario. The second half of Steve Kinney’s line is the real point: the six-line version is simple; the hard part is the production-hardened version — context compression, dead-loop detection, cost budgeting, graceful shutdown. These are precisely the things missing from your sixty lines.

The first wall is context. Every time your loop turns, messages grows a notch longer, and everything the tools return piles up in there too. A real task running for dozens of steps quickly blows past the model’s context window — or even if it doesn’t blow up, it’s stuffed with irrelevant content, the signal drowned in noise, and the model starts forgetting things and hallucinating steps it “decided earlier.” Someone wrote a whole piece on this: enlarging the context window mostly just postpones failure rather than solving it.

The second wall is money. Every notch the context grows, the API cost of each step rises with it. In production it’s not unusual for a single agent run to burn twenty or thirty dollars. You’re left with three choices: send the minimal context and get worse results; send the full context and go bankrupt on cost; or honestly build a context-management system that decides what to bring into each step. Only the third is viable, and the third isn’t in your sixty lines.

The third wall is the loop itself. AutoGPT’s most famous failure back then was getting stuck in a “do nothing” dead loop, or googling repeatedly to figure out its own goal. Simon Willison relayed a darker, funnier example: an agent realized it was stuck in an infinite loop and just used pkill to kill its own process. That max steps line of yours can block the dumbest kind, but it can’t stop it from going in circles within ten steps.

Add up these walls and you get that not-so-pretty number from the industry. Data compiled by Fiddler shows that in production, agent task failure rates run between 70% and 95%; on the WebArena benchmark, the best GPT-4 agent’s end-to-end success rate is only 14.41%, versus 78.24% for humans; CMU found agents fail at roughly 70% of common office tasks.

These numbers aren’t meant to talk you out of writing one. Quite the opposite — they explain why the MVP is worth writing: the greatest value of those sixty lines isn’t doing the work for you, it’s exposing these several walls all at once, at the fastest speed and lowest cost, right in front of you. Only after you’ve personally hit context explosion, hit tool timeouts, hit dead loops do you understand what those Memory, Executor, and Callback things in the framework are actually solving. HumanLayer’s Dexter Horthy distilled this production experience into 12-factor agents: many teams start a new project, bring in an agent framework, and no matter what they do with the out-of-the-box tools they can’t cross the 70%–80% reliability line; the ones who actually succeed instead take the small, specialized concepts inside an agent and fold them, bit by bit, into their existing product.

What You Should Do Next

Forget the framework for now. Tonight, type in those sixty lines above and hook them up to a real task of your own — read some directory on your computer, query an API, crunch some numbers, anything, as long as it’s something you actually want. Get it running in your terminal and watch the thought → action → observation notes go back and forth. What this step gives you is something no doc can: you finally know what an agent actually is.

Once it runs, before you hit the walls, use four questions to judge whether you really need to add anything. Both Anthropic’s and OpenAI’s practical guides cover this line of questioning. First, is this task’s path fixed or open? If the path is fixed, don’t bother with an agent — a plain workflow script is more stable and cheaper. Second, how many tools do you need? For a one- or two-tool job, the hand-built version is plenty. Third, do you need multi-step reasoning, and do you need to change your mind based on intermediate results? Only if yes does the agent loop truly come into its own. Fourth, how high are the reliability requirements? For your own use, a 70% success rate is tolerable; handing it to a customer is engineering of another order of magnitude, and none of the walls above can be dodged.

When should you bring in a framework? After you hit a wall, pick by the shape of the wall. Context blew up — then go look at context management; need to orchestrate several agents collaborating — then go look at the orchestration layer; need observability and to trace every step — then go hook up the corresponding tools. The 12-factor agents experience is that successful teams rarely stack an entire framework from scratch; instead they pick out the small modules they need and embed them into the sixty lines they already got running. Frameworks are for filling walls, not for breaking ground.

That person talked out of it by seventeen tabs on a Friday night — if he’d swapped the order, written the sixty lines first, then hit the walls, then patched as needed — his little assistant that checks the weather, reads files, and crunches accounts really could have run in a single evening. In your terminal tonight, do you want to run one too?

Comments

Select any text to comment on a specific part. Existing inline comments appear as small numbered bubbles. Powered by GitHub Discussions.