Your first agent: a tool-using loop
Assemble the pieces into a minimal working agent — and see why it needs guardrails.
Now assemble the atom, the loop, and tools into a working agent. The pseudocode below is deliberately framework-free so you see the whole machine:
def run_agent(goal, tools, max_steps=8):
messages = [{"role": "user", "content": goal}]
for step in range(max_steps): # a stop condition!
response = model.call(messages, tools=tools) # reason
if response.tool_call:
result = execute(response.tool_call) # act
messages.append(response) # record what it did
messages.append(tool_result(result)) # observe
else:
return response.text # done
return "Stopped: hit step limit."
That's a real agent. The model reasons with tools available; if it requests one, you execute it and feed the result back; if it answers without a tool call, you're done. Everything else in this course refines this skeleton.
Look at what's already here, because two lines are quietly doing reliability work. The max_steps cap is a stop condition — without it, a confused model can loop forever. And feeding the tool result back as an observation is the ground truth that keeps the agent connected to reality. Even this toy is designed for failure, and that's the right instinct.
In practice you'll likely use a framework — OpenAI Agents SDK for a clean built-in loop, LangGraph for stateful orchestration with persistence and human-in-the-loop, CrewAI for fast multi-agent prototypes. But heed Anthropic's advice: start with the raw model API, understand what's under the hood, and reduce abstraction as you go to production. Frameworks hide the prompts and the loop — convenient until you're debugging, when that hidden layer is exactly what you need to see. Build the loop by hand once; then a framework is a labor-saver, not a black box.
Run your skeleton on a simple multi-step task and watch it work — the model calling tools, results flowing back, an answer emerging. Then watch it fail: give it a task it can't complete and see it burn all your steps, or a vague tool and see it misfire. That failure is the honest starting point for Modules 2 and 3, where we make this reliable enough to trust.
Implement the loop above with one or two real tools (even a calculator and a web-search stub). Run it on a two-step task. Then remove the `max_steps` guard, give it an impossible goal, and observe why that guard exists.
Enjoying the free lessons? Get an email when we publish new courses and updates — no spam, unsubscribe anytime.
Discussion (0)
Ask a question or share what worked for you. Comments are reviewed before they appear.
No comments yet. Be the first to start the discussion!