AI Agents courseLesson 1 of 7
AI Agents course · Lesson 1 of 7
What Are AI Agents? How the Agent Loop Works, with Code
What AI agents are and how they work: goals, tools, observations and the agent loop, with real-world examples and a small agent in Python you can run.
On this page
An AI agent is a system in which a language model works towards a goal by choosing actions, usually calls to tools, looking at the results, and deciding what to do next, again and again, until the goal is reached. A chatbot answers a message. An agent completes a task: it might look up an order, check the delivery, and draft a message to the customer, deciding each step as it goes.
The parts of an agent
- A model that reads the goal and everything observed so far, and decides the next action.
- Tools: functions the agent can call, such as searching documents, querying a database or calling an API. See tool calling.
- Memory: the history of actions and results in this task, and sometimes facts kept between tasks.
- Limits and rules set in code: which tools exist, what each may do, how many steps are allowed, and which actions need a person’s approval.
The agent loop
- Read the goal and what has happened so far.
- Decide the next action (a tool and its arguments), or decide the task is finished.
- Run the tool, in your code, with your checks.
- Add the result to the observations.
- Repeat, up to a step limit.
This example runs that loop. The decisions come from a short scripted stand-in, so the code runs anywhere; a real model makes the same kind of decision from the goal and observations, in the same format.
import json
# Tools the agent may use. Each one is ordinary code with its own checks.
ORDERS = {"A-1042": {"customer": "c-7", "status": "delayed", "shipment": "S-88"}}
SHIPMENTS = {"S-88": {"carrier_status": "held at depot", "new_eta": "2026-11-05"}}
def get_order(order_id):
return ORDERS.get(order_id, {"error": "not found"})
def get_shipment(shipment_id):
return SHIPMENTS.get(shipment_id, {"error": "not found"})
def draft_message(text):
return {"draft": text} # drafts only: a person or a rule approves before anything is sent
TOOLS = {"get_order": get_order, "get_shipment": get_shipment, "draft_message": draft_message}
# Stand-in for the model's decisions, so the example runs anywhere. A real model reads the goal and
# everything observed so far, and chooses the next tool and arguments in the same format.
def decide(goal, observations):
if not observations:
return {"tool": "get_order", "args": {"order_id": "A-1042"}}
last = observations[-1]["result"]
if "shipment" in last:
return {"tool": "get_shipment", "args": {"shipment_id": last["shipment"]}}
if "new_eta" in last:
return {"tool": "draft_message", "args": {"text": f"Sorry, your order is {last['carrier_status']}. "
f"New delivery date: {last['new_eta']}."}}
return {"finish": observations[-1]["result"]}
def run_agent(goal, max_steps=5):
observations = []
for step in range(1, max_steps + 1): # hard limit on steps
action = decide(goal, observations)
if "finish" in action:
return action["finish"]
result = TOOLS[action["tool"]](**action["args"])
print(f"step {step}: {action['tool']}({json.dumps(action['args'])}) -> {result}")
observations.append({"action": action, "result": result})
return {"error": "step limit reached"}
print("final:", run_agent("Find out why order A-1042 is late and draft a message to the customer"))
step 1: get_order({"order_id": "A-1042"}) -> {'customer': 'c-7', 'status': 'delayed', 'shipment': 'S-88'}
step 2: get_shipment({"shipment_id": "S-88"}) -> {'carrier_status': 'held at depot', 'new_eta': '2026-11-05'}
step 3: draft_message({"text": "Sorry, your order is held at depot. New delivery date: 2026-11-05."}) -> {'draft': 'Sorry, your order is held at depot. New delivery date: 2026-11-05.'}
final: {'draft': 'Sorry, your order is held at depot. New delivery date: 2026-11-05.'}
The agent did not know in advance that it would need the shipment: it learned that from the order, then chose the next tool. That is the difference from a fixed script. Notice also what the code controls: the list of tools, the step limit, and that messages are only drafted, not sent.
Good uses for agents
- Investigations where the next step depends on what you find: why a payment failed, why a pipeline broke.
- Multi-step requests across systems: check stock, reserve it, create the order, confirm.
- Research and summarising across several sources.
- Coding assistants that read code, make changes, run tests and fix failures.
When not to use an agent
If the steps are always the same, a workflow with fixed steps is cheaper, faster and easier to test. Agents add cost, delay and unpredictability, so use them only where the flexibility pays off. The next lesson compares the two: workflows vs agents.
Common mistakes
- No step or cost limit, so a confused agent loops.
- Letting the agent act without approval on payments, deletions or messages to customers.
- Too many tools with vague descriptions, so the model picks the wrong one.
- No evaluation: agents must be tested on realistic tasks, several times each. See evaluating and securing agents.
Key takeaway
An AI agent is a model choosing tools in a loop, observing results and deciding the next step until the goal is met. Your code provides the tools, runs them with checks, and sets limits and approval rules. Use agents where the path depends on what is found, and simpler workflows everywhere else. For the difference between “AI agents” and “agentic AI”, see AI agents vs agentic AI.
Progress is saved in this browser only. No account needed.

