Day 120 · An intern with a to-do list

Agents I — The Loop

You will be able to
  • Define an agent as LLM + tools + loop and identify each part in running code
  • Implement the ReAct-style loop: decide → act → observe → decide, with tool errors fed back as observations
  • Enforce stopping criteria and budgets (steps, tokens, time) and explain why every agent needs them
  • Apply the when-NOT-to-build-an-agent checklist to three candidate tasks
Today's ~120 minutes
Spaced-rep: due cards + restate the capstone brief from memory (D119)10 min
ELI5 + tech read; agent-loop visualizer lap by lap20 min
Guided: build the loop + agent-or-not verdicts42 min
Practice: the grep tool upgrade20 min
Project: refactor into agent/core.py with tests20 min
Quiz + flashcards8 min

Builds on: Day 111Tool use & function calling · Day 106LLM APIs — the request · Day 113RAG architecture

The analogy

On Day 111 you gave the polymath hands: it could call one tool when you asked one question. An agent is the next step — an intern with a to-do list and permission to keep working. You say "find out which config file sets our API rate limit," and the intern doesn't answer from memory. She walks to the filing room, lists the folders, opens the likely one, reads it, doesn't find it, opens the next, finds the line, and comes back with the answer AND how she got it.

The magic isn't intelligence — it's the loop. Look at the situation, pick ONE next action, do it, look at what happened, repeat. Each trip around the loop the intern knows more than the last trip, because the results of her actions pile up in her notes. And crucially, a good intern knows when to stop: when she has the answer, when she's out of places to look ("I checked every file — it isn't there"), or when she's spent too long ("this is taking hours, let me check in"). An intern with no stopping rule reorganizes the filing room until midnight. Yours will too, unless you build the clock in.

Why this matters on the job

"Agentic" is the most-hyped word in AI engineering, and the fastest way to stand out — in interviews and with customers — is demonstrating you know what the word mechanically means: a while-loop around an LLM that chooses tool calls, with observations accumulating in context. Every agent product you'll ever debug (coding agents, support agents, research agents) is this loop wearing different tools. FDEs also field the opposite conversation weekly: a customer wants "an agent" for a task that is actually a 3-step fixed pipeline — cheaper, faster, testable. Knowing when NOT to build the loop is billable judgment. Days 121–126 all build on the file you write today.

Watch it happen

An intern with a to-do list — the agent loop, step by step

step 1 / 5
goal
diagnose order #4412, draft reply
scratchpad
(empty)
tools
lookup_order(id)
search_docs(q)
draft_email(text)

Task: "Find why order #4412 failed and draft a reply." The agent holds a goal, a scratchpad, and tools.

Guided practice

guided 1

Build the loop: a file-Q&A agent in 70 lines

30 min
  1. Create agent_v0.py with the starter code. It has all three parts labeled: TOOLS (three real functions over an in-memory filesystem), a ScriptedLLM (a deterministic stand-in policy so the LOOP runs in-browser — locally you swap in your Day 107 client and the Day 111 tool-use API, and nothing else changes), and run_agent, the loop itself.
  2. Run task 1: "Which config file sets the API rate limit, and to what value?" Read the printed trace lap by lap: list_files → read the likeliest file → not there → read the next → found → final answer. Notice the answer cites the file it actually read.
  3. Run task 2: "What is the database password?" — it is nowhere in the corpus. Watch the agent read everything, then give the honest give-up answer. Circle where in the ScriptedLLM that honesty lives (the fallback branch) — with a real LLM, that behavior comes from the system prompt: "if the information is not found after checking plausible files, say so."
  4. Break a tool: rename a file in FS so the scripted policy requests a missing file, and confirm the TOOL ERROR comes back as an observation and the loop continues rather than crashing. Errors are observations.
  5. Set max_steps=2 and rerun task 1: budget exhaustion fires mid-investigation. This is the seatbelt — leave it on.
🐍 python — editable, runs in your browser
Ctrl/⌘+Enter runs · Tab indents · numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)
guided 2

Agent or not? Three verdicts

12 min

For each task below, decide: agent, fixed workflow, or plain RAG — then write the one-sentence justification. Check against the key only when done.

  1. "Every Monday, pull last week's tickets, summarize by category, email the report." Same steps every time, zero exploration.
  2. "Find why the staging deploy is failing." Unknown cause; next action depends on each log you read.
  3. "Answer employee policy questions from the handbook." One retrieval + one grounded generation per question.

Key: 1 = fixed workflow (the path is knowable in advance — an agent adds variance to a task that tolerates none); 2 = agent (genuinely open-ended investigation, the D120 loop's home turf); 3 = plain RAG (your capstone! — no loop needed until questions require multi-hop, and even then Day 118's decomposition may suffice). If you said "agent" for all three, reread the checklist — that instinct is the expensive one.

On your own

Teach the agent a new trick without touching the loop

20 min

Add a third tool grep(pattern) that returns {filename: [matching lines]} across all of FS, and extend the ScriptedLLM to prefer one grep over reading files one by one for "find the line" tasks. Then run the rate-limit task again and compare traces: the grep-enabled agent should finish in 2 steps instead of 3-4.

Constraints: run_agent must not change at all — that is the point of the tool abstraction; only TOOLS and the policy change. Hints: policy order — grep first if no grep observation exists; answer from the grep observation if it hits; fall back to read_file. Note what you just felt: better tools shrink the loop. That lesson — invest in tools, not cleverer loops — is half of agent engineering.

Ship before you stop

agent_v0 becomes a module

Refactor today's lab into a committed module the rest of Week 18 builds on: agent/core.py with run_agent(llm, tools, task, max_steps, on_step=None) — the on_step callback receives each (step, action, obs) for logging (Day 125's audit trail will hook in here); agent/tools_fs.py with the three file tools plus docstrings written as if for the model (they become tool descriptions in the real API); and tests/test_loop.py with four pytest cases: happy path finds the answer, honest give-up on absent info, tool error fed back as observation (loop continues), and max_steps stops a runaway policy (write a deliberately stuck ScriptedLLM for this). Include a README section mapping each piece to its real-LLM equivalent.

Rubric — check what you completed (0/6)

Common mistakes & misconceptions

  • Letting the model "execute" tools. The model only ever emits a request; your code validates and executes. Blurring this line is how agents delete files nobody asked them to.
  • Hiding tool errors from the model. A swallowed exception leaves the agent reasoning from a stale world-model; the error string IS the steering signal for the next lap.
  • Shipping a loop with no budget "because it terminates in testing." Production inputs find the infinite loop; max steps, cost caps, and timeouts are day-one requirements, not hardening.
  • Treating an honest "not found" as a failure to prompt away. Calibrated give-ups are a success mode; punishing them breeds confident fabrication — the worst agent behavior.
  • Building an agent where a workflow suffices. If you can write the step sequence down in advance, do that — cheaper, faster, testable, explainable to the customer.
  • Growing the loop instead of the tools. A grep tool beat a smarter policy today; when an agent flails, upgrade its tools and their descriptions before touching the loop.
Knowledge check

Q1. What are the three components that make something an agent, per today's definition?

Q2. A tool call throws an exception mid-run. The correct handling is…

Q3. A customer wants "an agent" to generate the same three-section weekly report from the same two data sources. Your recommendation?

Go deeper — curated resources

articleAnthropic — Building Effective Agents (workflows vs agents)30 minarticleLilian Weng — LLM Powered Autonomous Agents (loop & tools sections)30 mindocsClaude Docs — Tool Use overview (the real API for the swap)20 min
If you have a third hour
  • ReAct paper (Yao et al. 2022)The origin of reason-act interleaving. Skim §2 and the Wikipedia-QA traces; you built exactly this today, minus the academic benchmarks.
Done means
  • Loop runs both tasks; honest give-up and budget stop both demonstrated
  • Tool-error experiment run: loop continues with the error as observation
  • All three agent-or-not verdicts match the key with sound reasoning
  • agent/core.py committed with four passing tests
  • Quiz ≥ 2/3
How this connects

← Back: Day 111's tool loop was one lap; today you closed it into a cycle. The honest give-up is Day 113's "insufficient context" escape hatch reborn as agent behavior.

Forward →: Day 121 adds a planner on top of this exact module, Day 122 gives it memory, Day 125 hardens it, and on Day 126 it triages support tickets with your capstone's retrieval as one of its tools.

Unlocks: D121 Agents II — Planning & Decomposition · D122 Agents III — Memory & Context · D123 Multi-Agent & Workflow Patterns · D124 Model Context Protocol