Lesson 01 What Is an Agent
Theme:

Lab 01 — Trace an Agent on Paper

Lesson 01 · Lab Guide · ~25 min · no code, no API keys

L01 has no Python yet. The point of this lab is to internalise the agent loop before L02 turns it into ~80 lines of code. By the end you'll have hand-simulated one full agent loop on paper, labelled each of the four building blocks inside a real transcript, and named the stop condition that fired. That mental model is what L02's code will make literal.

1. Prereqs

Read the L01 theory page first — this lab assumes you've seen the working definition ("an agent is a program whose control flow is driven by an LLM's output"), the four building blocks (model, tools, memory, planner/loop), and the four stop conditions (natural exit, turn cap, cost cap, user interrupt).

You don't need software, API keys, or an editor. Grab a pad and a pen, or open a blank text file. You'll be writing down a growing conversation list turn by turn.

2. The scenario

A user asks an agent:

"What's the current weather in Kyiv, and should I bring a jacket?"

The agent has access to exactly two tools:

Your job is to play the runtime: drive the loop, dispatch tool calls, append results, and stop when the LLM says it's done.

3. Step 1 — Write the system prompt

Before any turns happen, a developer writes a system prompt that defines the agent's role and tools. Draft 2–3 sentences a developer might use for this scenario, then compare with the reference below.

Reference system prompt:

You are a helpful assistant with access to two tools: get_weather and
get_clothing_advice. Use them to answer the user's question. When you
have enough information, give the final answer in one sentence.

Write this down at the top of your page as the first message in the conversation (role: system). Then add the user's question as message #2 (role: user). The conversation list now has 2 entries.

4. Step 2 — Trace turn 1

The runtime sends the conversation to the LLM and gets back a response. Below is a plausible turn-1 output. Write it into your conversation list as message #3 (role: assistant), then answer three questions in the margin: which tool was called, what arguments were used, and what stop_reason the runtime should see.

LLM turn 1 output:
  - text: "I'll check the weather first."
  - tool_use: {name: "get_weather", input: {city: "Kyiv"}}
  - stop_reason: "tool_use"

Reference answers: tool = get_weather; argument = {city: "Kyiv"}; stop_reason = "tool_use". Because the stop reason is not "end_turn", the loop must continue.

5. Step 3 — Execute the tool, write the observation

The LLM does not execute tools. The runtime does. Write down the runtime's two-step job:

  1. Call get_weather("Kyiv") — pretend it returns "4°C, light rain".
  2. Append a tool_result message to the conversation as message #4.

Reference tool-result message:

{role: "user",
 content: [{type: "tool_result",
            tool_use_id: "X",
            content: "4°C, light rain"}]}

Notice the role: it's user, not tool. That's the Anthropic API convention — the runtime pretends to be the user when feeding tool output back to the model. (L02 covers this in code; for now, just write it down.)

6. Step 4 — Trace turn 2

The runtime sends the updated conversation (4 messages so far) back to the LLM. Plausible turn-2 output:

LLM turn 2 output:
  - tool_use: {name: "get_clothing_advice",
               input: {temp_c: 4, condition: "light rain"}}
  - stop_reason: "tool_use"

Append this as message #5 (role: assistant). Decide in the margin: continue the loop, or stop?

Reference: continue. The stop reason is again "tool_use" — another tool call. The natural-exit condition has not fired yet.

As the runtime, call get_clothing_advice(4, "light rain") — pretend it returns "Bring a waterproof jacket and a hat." — and append a tool_result message as #6. The conversation list is now 6 entries deep.

7. Step 5 — Trace turn 3 and stop

Third call to the LLM. With both tool results in context, the model has enough information to answer:

LLM turn 3 output:
  - text: "It's 4°C with light rain in Kyiv — bring a waterproof
           jacket and a hat."
  - stop_reason: "end_turn"

Append as message #7. Now look at stop_reason: it's "end_turn", which means the model is done — no more tool calls coming. The loop exits. This is the natural-exit stop condition from L01 theory section 6.

8. Step 6 — Identify the four building blocks in this trace

Now flip back over your conversation list and label, in your own words, where each of the four building blocks shows up in the trace. Then compare with the reference answers.

9. Step 7 — Which stop condition fired?

Reference: the natural-exit condition — stop_reason == "end_turn" on turn 3. The other three conditions (turn cap, cost cap, user interrupt) were never tested in this trace, but the agent's runtime would still have been checking them on every iteration.

Now do a quick thought experiment: what would have happened if turn 2's LLM output had also called get_weather again, instead of get_clothing_advice? And then turn 3 did the same thing? And turn 4? And so on?

Answer: infinite loop — unless the turn-cap stop condition (or a cost cap) is also in place. That's why L01 theory insists every agent needs all four stop conditions, not just the natural-exit one. The natural-exit condition only protects you when the model is well-behaved.

10. What you should leave with

A page of notes that looks roughly like this:

This is the mental model L02 will turn into code. When the L02 lab opens with messages = [] and a while True: loop, you'll already know exactly what that list looks like at every step, what gets appended, and when the loop breaks.

11. Troubleshooting (mental model)

Common confusions while doing this trace