Model, Tools, Loop
Strip the marketing off and an agent is three parts wired in a circle. This lesson names them, runs one, and shows exactly what you are left with when you remove each.
Welcome to AI Agents & Automation 🤖
North of the city there is a commercial greenhouse. Six zones: seedling trays in 1 and 2, tomato rows in 3 through 6. Every morning a grower walks the rows with a moisture meter, checks the forecast on their phone, and decides which zones get water and for how long. It takes forty minutes, and it is roughly the same forty minutes every day.
That job is the shape this entire course is about. It is not a question with an answer. It is a loop: look at the world, decide something, change the world, look again.
GH-North is our workbench from here through module 9, partly because we can break it without anybody losing money, and mostly because irrigation control genuinely is a control loop. The domain and the ideas reinforce each other.
Start with the definition, because the word "agent" has been stretched until it barely means anything. In this course it means exactly three things wired together:
- A model that reads the situation and decides what to do next
- Tools that let a decision reach the real world
- A loop that feeds the result of the last action back in as the input to the next decision
Remove any one of the three and you still have something useful. You no longer have an agent.
Control engineers have had a name for this shape for a century, and it is a better name than "agent": a control loop.
A thermostat is a control loop. It senses (reads the room temperature), decides (compares that to a setpoint), and actuates (closes a relay to the boiler). Then it does it again, forever. Nobody thinks a thermostat is intelligent, and everybody trusts it to run unattended, because its three beats are simple, bounded, and inspectable.
An LLM agent is that exact shape with a far more capable decider bolted into the middle:
- Sense: tool results, retrieved documents, and everything said so far arrive as text in the model's context
- Decide: the model emits either a tool call or a final answer
- Actuate: your code executes the requested tool and feeds the result back in
This course de-personifies the model on purpose. It is not a colleague, an assistant, or a junior anything. It is the decide stage of a control system that happens to be made of tokens. That framing pays for itself later: it makes "what is this thing physically able to touch?" the obvious first question, and it makes a runaway agent feel like what it really is, a controller stuck in a bad limit cycle, rather than a robot with a bad attitude.
Four systems are described below. By this lesson's three-ingredient definition, which one is an agent?
- AA model given six tool definitions: it emits a call, your code runs it, the result is appended, and the model is called again with the updated messages until it emits a final answer
- BA model given six tool definitions: it emits one call, your code runs it, prints the result for the grower, and exits
- CA nightly script that reads all six moisture sensors and irrigates any zone below 30 percent
- DA model asked to draft an irrigation schedule, re-prompted five times to critique and improve its own draft, with no tool access at all
Here is the whole thing, stripped of every convenience a framework would add:
messages = [
{"role": "system", "content": INSTRUCTIONS},
{"role": "user", "content": "Water whatever needs it in GH-North."},
]
for turn in range(MAX_TURNS):
reply = model.respond(messages=messages, tools=TOOLS) # decide
messages.append(reply)
if not reply.tool_calls: # stop condition: the model answered
return reply.content
for call in reply.tool_calls: # actuate
result = EXECUTORS[call.name](**call.arguments)
# (this pseudo-SDK parses arguments for you; on the wire they are a JSON string, lesson 1.5)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result), # sense: back in as text
})That is an agent. Twelve lines and a comment. Every product you have seen demoed is this plus retries, budgets, logging, permissions, and a user interface.
Notice where the parts live. All of the intelligence is inside model.respond, which you did not write. All of the safety is inside EXECUTORS and MAX_TURNS, which you did. That split is the entire job description for the rest of this course.
Take the loop exactly as written. MAX_TURNS is 4, and on all four responses the model emits a tool call and never a final answer. How many times does model.respond run, and what does the function return?
for turn in range(MAX_TURNS):
reply = model.respond(messages=messages, tools=TOOLS)
messages.append(reply)
if not reply.tool_calls:
return reply.content
for call in reply.tool_calls:
result = EXECUTORS[call.name](**call.arguments)
messages.append({"role": "tool", "tool_call_id": call.id,
"content": json.dumps(result)})- AIt runs 4 times and the function returns None: the loop ends by exhausting range(MAX_TURNS), and there is no return statement after it
- BIt runs 4 times and the function returns the last tool result, since that is the final value computed
- CIt runs 5 times: one extra call is made after the loop to produce a final answer
- DIt raises an exception when the turn budget is exhausted, because the run did not finish
Now take the three ingredients away one at a time. Each removal leaves you with a real, common piece of software, and knowing their names keeps you honest about what you have actually built.
Model plus tools, no loop is a single function call. The model picks one tool, your code runs it, you show the result. This is most of the "AI features" shipping in most products, and it is very often the correct design. Model plus loop, no tools is a monologue. It can draft, critique itself, and redraft all day. Nothing it says changes anything outside the transcript, which makes it safe and also makes it not an agent. Tools plus loop, no model is a script. The cron job that waters zone 3 for ten minutes at 6am is exactly this, and it has been running without incident since 2019.That third one deserves genuine respect. A script is faster, cheaper, reproducible, and it has never once invented a zone 9. Most of the time the honest answer to "should this be an agent?" is no. Lesson 1.4 gives you the rule for deciding.
Name the missing ingredient. Without it you have a single tool call, not an agent, because no result ever feeds back in as the next input.
Three ingredients: a model, tools, and a ____ that feeds each result back in.- An agent is exactly three things wired in a circle: a model that decides, tools that reach the world, and a loop that feeds results back in.
- The controlling frame for this course is a control loop: sense, decide, actuate. The model is the decide stage, not a person.
- The loop itself is about twelve lines. The intelligence lives in the model; the safety lives in your executors and your turn budget.
- Remove one ingredient and you get a single call, a monologue, or a script. All three are respectable, and the script is often the right answer.
- A run that exhausts its turn budget does not raise. It fails quietly unless you make it fail loudly.
Next: what agents genuinely close in production, and why it looks nothing like the demo.