linuxtoasterblog → agents are loops, not runtimes

Agents Are Loops, Not Runtimes | LinuxToaster

An agent is a loop plus a prompt plus a side effect. Everything else is packaging.

There is an industry being built right now around the word "agent." It has SDKs, it has frameworks, it has orchestration layers, it has observability platforms, it has a graph representation of tool-calls, and it has conference tracks. What it does not have, mostly, is a clear answer to the question: what is an agent, really?

Here is a clear answer. An agent is a loop plus a prompt plus a side effect.

That is the whole thing. Everything else is packaging.

The shortest agent

7 times toast "refine for publishing" < draft.md

This is an agent. It has a loop — seven iterations. It has a prompt — "refine for publishing." It has a side effect — the document is transformed. The model reads its own output on each pass and improves it. That is autonomous iterative refinement, which is the marketing copy for half the agent platforms on the market, and it fits on one line of a shell.

while true
  tail -n 50 /var/log/nginx/error.log | toast "new 5xx patterns? yes/no + summary" | set verdict
  if contains $verdict "yes"
    echo $verdict | curl -X POST -d @- $SLACK_HOOK
  end
  sleep 60
times

This is a monitoring agent. It watches, it decides, it acts, it repeats. It has state. It has a tool (curl). It has a feedback loop. It is also six lines of shell.

Neither of these required a framework. Neither required a runtime. Neither required an SDK. They required a loop, a prompt, and a side effect.

Where frameworks come from

Agent frameworks are not fraudulent. They are a solution to a real problem — just not the one they advertise.

The real problem is that most programming languages treat shelling out as an escape hatch. Python subprocess, Node child_process, Go os/exec — these work, but they feel like leaving the language. So when developers want to orchestrate LLMs, they instinctively reach for in-language primitives: an HTTP client to call the API, a JSON parser for the response, a class hierarchy for "tools," a state machine for multi-step flows, a retry library for transient failures.

Put those together and you have rebuilt, poorly, what the shell already does. The shell was designed in 1973 for exactly this problem: compose small tools, pipe data between them, handle failures, retry, run things in sequence or parallel. An LLM is a new kind of small tool. The shell does not care that it is non-deterministic. It just wants stdin and stdout.

The framework industry exists because the Python ecosystem has no idiomatic way to say "pipe the output of this thing into that thing, seven times, with retries." In bash it is one line. In a framework it is a class hierarchy.

The cost of the abstraction

Every framework layer between your prompt and your side effect is a layer you now have to understand, debug, and upgrade. The framework has opinions about retry semantics, logging, serialization, memory, tool-calling schema. Its opinions are almost certainly different from yours. When something breaks in production, you are debugging the framework's idea of an agent, not your agent.

This is not a new observation. It is the same observation people made about enterprise Java, about Rails plugins, about web frameworks in general. The abstraction saves you effort on day one and costs you effort forever after. That trade is worth it when the abstraction handles something genuinely hard. Most agent frameworks are not handling something genuinely hard. They are handling loops, retries, and string concatenation.

You already have a tool for loops, retries, and string concatenation. It is called Unix.

What a runtime actually buys you

There are real reasons to use a framework or a runtime, and it is worth being honest about them.

Multi-tenant execution with isolation, where untrusted users can submit workflows and you need to sandbox them — yes, you need infrastructure for that. Distributed execution across a fleet with dynamic scheduling and failure handling — fine, use Temporal or something like it. A production system with strong SLAs, detailed tracing, and a compliance audit trail — reasonable case for a platform.

But these are infrastructure problems, not agent problems. They would be true whether you were running LLM calls or image resizing or invoice processing. The "agent" part is incidental. What you are really buying is a job queue with observability. Call it that.

For the other ninety percent of cases — a developer on their machine, a script on a server, a cron job, a CI pipeline — a loop plus a prompt plus a side effect is the right shape. Adding a runtime adds weight without adding capability.

The composition principle

The reason pipes work as an API for LLMs is the same reason they worked for grep | sort | uniq fifty years ago. A pipe makes no assumptions about its endpoints. Text flows in one direction. Tools can be added, removed, swapped. The output of any stage is the input of any other.

A model in the middle of a pipe is just another tool. It takes text, produces text. The text it produces might be code, might be JSON, might be prose, might be a decision. The next tool in the pipe handles it the same way it would handle awk output — parse what you need, ignore what you don't.

This is why jam — the shell we wrote when bash quoting broke under the weight of LLM prompts — has times and while as built-in primitives. Not because loops are complicated, but because building an agent should feel like writing shell, not like configuring a platform.

The test

Here is a test for whether you need an agent framework. Write your agent as a shell pipeline. If the pipeline fits in ten lines and does what you need, you do not need a framework. If it does not fit in ten lines, ask what specifically cannot be expressed in pipes. Usually the answer is something like "stateful multi-turn conversation with tool use and memory." Then ask whether that state really needs to live in code, or whether it could be a file on disk — .crumbs, .chat, whatever your convention.

Most of the time the state can be a file. Most of the time the loop can be while. Most of the time the tool calls can be commands. Most of the time the framework is adding weight, not capability.

Closing

The agent-framework industry will keep growing because there is money in selling abstractions to people who do not want to think about the underlying substrate. That is fine. Abstractions are useful when they save real effort.

But before you pick one, try the shell version first. Write the loop. Write the prompt. Write the side effect. Run it. See how far that gets you. It will get you further than the frameworks suggest. A lot of people have been sold a runtime when what they needed was while.

An agent is a loop plus a prompt plus a side effect. Unix already has two of those. The model provides the third.

This essay is part of LinuxToaster — Unix re-imagined for the era of AI.