Foundations and landscape: a short history, the anatomy of an agent, compound AI systems, workflows versus agents, and the hard parts.
CreditThis coursework is adapted from, and inspired by, Stanford CS329Z: Engineering AI Agents (Diyi Yang, Michael Ryan, John Yang), Week 1, "Foundations & Landscape Introduction: What Are Agentic Systems?" The topic list and the three required readings come from that course's public schedule [8]. The notes, lab, quiz and assignment are original writing. This is not an official Stanford document. I did not copy the lecture slides.
Most people first meet a language model as a chat box. You type. It answers. That is one model call.
Real products rarely stop there. They add search, code runners, databases, checks and retries. Some let the model choose its own next step. This course calls all of these agentic systems. They sit on a range. At one end is a plain LLM pipeline. At the other end is a model that runs on its own for many steps.
Week 1 gives you the map. You learn the vocabulary, the parts, and the main trade-offs. Later weeks go deep on each part: retrieval, tools, memory, evaluation, safety and more [8].
By the end of this week you should be able to:
| Part | What you do | Time |
|---|---|---|
| Reading | Three required readings, plus optional ones (reading guide) | 3 h |
| Lecture notes | Work through section 2. Redraw the diagrams from memory. | 1.5 h |
| Lab | Run, read and extend the agent loop | 1.5 h |
| Discussion and quiz | Talk it through with a partner, then take the quiz | 1 h |
| Assignment | Small graded project (section 7) | 1 h to 2 h |
PrerequisitesYou can read basic Python. You have used a chat model. You do not need machine learning math. You do not need an API key. The lab runs offline with a mock model.
The word "agent" is old. It did not start with chatbots.
In the standard AI textbook, an agent is something that perceives its environment and acts on it [7]. Kapoor et al. point out one funny result of this: a thermostat counts [3]. It senses the temperature. It turns the furnace on or off.
That is a useful baseline. It shows that "agent" is a weak word on its own. What matters is how much it can sense, decide and do.
Early AI agents ran on hand-written rules. A rule has a condition and an action. "If the temperature is below 70 and the furnace is off, turn the furnace on." Newell and Simon used exactly this thermostat example in their 1972 book on human problem solving [6].
Researchers then built larger designs, called cognitive architectures. Soar is a well-known one. They had working memory, long-term memory and a decision loop [6]. They worked, but they were limited to problems you could write down as logic. They also needed many pre-written rules [6].
Large language models changed the picture. A model trained on huge amounts of text can read any text input and write any text output. It does not need hand-written rules for each task. Around 2022 researchers began to put such a model in a loop with an environment.
Key idea"Agent" is a spectrum, not a yes-or-no label. Kapoor et al. say it is better to ask how agentic a system is than to ask whether it is an agent [3].
Most LLM agents have the same five parts. Figure 2 shows how they connect.
The model is the part that reads text and writes text. Weng calls it the agent's "brain" [2]. CoALA puts it as the core of a bigger design [6].
Two facts matter for builders.
Hard tasks need several steps. Weng splits planning into two jobs [2]:
ReAct is the simplest way to join thinking and acting. The model writes a short Thought, then an Action, and then it sees an Observation. This repeats [5]. ReAct treats a thought as a kind of action that only changes the agent's own context. It does not touch the outside world [5].
The ReAct paper has a clear finding. Reasoning alone (chain of thought) can invent facts, because it is not grounded in anything outside the model. On HotpotQA, hallucination caused 56% of the chain-of-thought failures the authors checked, against 0% for ReAct. But ReAct had its own problem: it could repeat the same thought and action in a loop [5]. Keep this in mind. We will meet loops again in the lab.
Weng borrows from human memory. She maps it to agents like this [2]:
| Human idea | Agent version |
|---|---|
| Short-term (working) memory | What is in the context window right now |
| Long-term memory | An outside store, often a vector database, searched when needed |
CoALA is more detailed. It names four kinds of memory [6]:
| Kind | What it holds | Example |
|---|---|---|
| Working | The current goal, recent inputs, results of thinking | The prompt for this step |
| Episodic | What happened in past runs | A log of earlier tasks and their results |
| Semantic | Facts about the world | A product catalog, a wiki |
| Procedural | How to act: the model weights and the agent's code | Your Python loop and prompt templates |
CoALA adds a warning. Letting an agent write to its own procedural memory (its own code) is riskier than letting it write notes. A bug there can change how the whole agent behaves [6].
A tool is a function the model can ask the program to run. Examples: web search, a calculator, a database query, a code runner, or an API call. Tools give the model things its weights lack: fresh facts, exact math, and the power to change something [2].
The model does not run the tool itself. It writes a request, such as a function name and arguments. Your program runs it and passes the result back as text. You will build exactly this in the lab.
Anthropic gives a practical rule. Spend as much effort on the tool interface as you would on a human interface. They call it the agent-computer interface. In their coding agent, they spent more time improving tools than improving the main prompt [4].
The environment is everything outside the agent that the agent can sense or change. It might be a web site, a folder of files, a user, or a test suite. Kapoor et al. say the more complex the environment, and the more open the goal, the more "agentic" the system is [3].
CoALA groups environments into three types: physical (robots), dialogue (people or other agents), and digital (APIs, web sites, code). Digital ones are cheaper and faster to work in, which is why most LLM agents live there [6].
One idea from Anthropic is worth remembering. At each step the agent should get "ground truth" from the environment, such as a tool result or a test run. That is how it can tell whether it is making progress [4].
| This course (Week 1) | Weng [2] | CoALA [6] |
|---|---|---|
| LLM core | The "brain" | Core of the architecture |
| Reasoning | Planning (subgoals, reflection) | Reasoning actions and the decision cycle |
| Memory | Short-term and long-term | Working, episodic, semantic, procedural |
| Tools | Tool use | External actions (grounding) |
| Environment | Not a separate part | Physical, dialogue, digital |
Zaharia et al. define a compound AI system as a system that solves AI tasks using several interacting parts. These include multiple calls to models, retrievers, and external tools. An AI model, in contrast, is just a statistical model, such as a Transformer that predicts the next token [1].
Why this mattersQuality is not only a model question. It is also a design question. You can often improve a product faster by changing the system around the model than by waiting for a better model [1].
The BAIR post gives four reasons [1]:
| System | Parts | How it works |
|---|---|---|
| AlphaCode 2 | Fine-tuned LLMs, code execution, clustering model | Generates up to 1 million solutions, then filters and scores them |
| AlphaGeometry | LLM and a symbolic math engine | The LLM suggests constructions. The engine checks what follows from them |
| Medprompt | GPT-4, nearest-neighbor search, chain-of-thought examples, ensembling | Finds similar solved questions to build a prompt, then votes over several answers |
| RAG systems | LLM and a retriever | Search first, then answer using the results |
Source for all rows: Zaharia et al. [1]. The same post reports that Databricks saw 60% of LLM applications using some form of retrieval-augmented generation (RAG) and 30% using multi-step chains.
| Problem | Plain meaning |
|---|---|
| Design space | Many choices: which models, which retriever, how many calls, how to split a fixed time or cost budget between parts. |
| Optimization | You cannot train the whole thing end to end. Search engines and code runners are not differentiable. Tools such as DSPy tune prompts and examples for the whole pipeline instead. |
| Operation | You must log and debug traces, manage data pipelines, and handle new security risks that single models do not have. |
Summary of [1].
The post also asks a design question that leads straight into the next section: should the control logic live in ordinary code, or should an LLM drive it [1]?
Anthropic draws one clear line. Both kinds are "agentic systems", but they differ in who controls the path [4].
| Workflow | Agent |
|---|---|
| LLMs and tools are orchestrated through predefined code paths. | LLMs dynamically direct their own processes and tool use, and keep control over how they do the task. |
| The developer decides the steps. | The model decides the steps. |
| Predictable. Easy to test. | Flexible. Harder to predict. |
| Pattern | What it does | Use it when |
|---|---|---|
| Prompt chaining | Splits a task into fixed steps. Each call uses the last output. You can add checks between steps. | The task splits cleanly into subtasks. You trade speed for accuracy. |
| Routing | Classifies the input and sends it to a specialist prompt or tool. | There are distinct categories and the classification is reliable. |
| Parallelization | Runs subtasks at once ("sectioning") or runs the same task several times ("voting"). | You want speed, or several attempts for higher confidence. |
| Orchestrator-workers | A central LLM breaks the task down, hands parts to workers, and combines results. | You cannot predict the subtasks in advance, such as multi-file code changes. |
| Evaluator-optimizer | One call writes. Another critiques. They loop. | You have clear criteria and feedback improves the result. |
Source: [4].
Anthropic describes agents as "typically just LLMs using tools based on environmental feedback in a loop" [4]. The agent starts from a command or a chat with a person. Once the task is clear, it plans and acts on its own. It may stop to ask a person. It should have stop rules, such as a maximum number of steps [4].
Kapoor et al. list three groups of factors that make a system more agentic [3]:
Anthropic's advice is blunt. Find the simplest solution that works. Add complexity only when it clearly helps. This may mean no agent at all. Often one well-prompted call with retrieval and examples is enough [4].
| Choose a workflow when… | Choose an agent when… |
|---|---|
| The steps are known ahead of time | You cannot predict how many steps are needed |
| You need steady, repeatable results | You need the model to choose its path |
| Cost and speed limits are tight | You can pay more for flexibility |
| Mistakes are costly | You can run in a sandbox, with checks, in a setting you trust |
Based on [4]. Anthropic adds that agents mean higher cost and a chance of errors that pile up, so they suggest tests in sandboxes and guardrails.
A note on datesThe Anthropic post now carries a banner saying that much of the tooling it describes has changed since December 2024 [4]. The definitions and the pattern list are still a good foundation. Check current docs before you pick a framework.
The lecture names four: reliability, training, safety and evaluation [8]. Here is what each means, with evidence from the readings.
| Challenge | One-line example | Main sources |
|---|---|---|
| Reliability | Ten steps at 95% each is about 60% overall | [2] [4] [5] |
| Training | Tuning a pipeline that has a search engine in it | [1] [3] |
| Safety | An action like "delete" or "send" needs a human check | [3] [4] [6] |
| Evaluation | A cheap retry loop beats a fancy agent on cost and accuracy | [3] |
Three readings are required. Four more are optional. For each one you get: why it matters, the key ideas, and questions to think about as you read. Read the questions first. Take short notes as you go.
How to read a paper or a long postPass 1: read the title, the intro and the conclusion (10 minutes). Pass 2: read the figures and tables. Pass 3: read the parts that matter for your questions. You do not need to read every appendix.
Zaharia, Khattab, Chen, Davis, Miller, Potts, Zou, Carbin, Frankle, Rao, Ghodsi. BAIR Blog, February 18, 2024. Read online · reference [1]
It gives you the key phrase for the whole course: compound AI system. It argues that building around a model matters as much as the model itself. The course site uses the same framing in its welcome text [8].
Lilian Weng. Lil'Log, June 23, 2023. Read online · reference [2]. The page lists a reading time of about 31 minutes.
It is the clearest early tour of how LLM agents are put together. Many later papers and posts use its three-part view: planning, memory, tool use.
Kapoor, Stroebl, Siegel, Nadgir, Narayanan. Transactions on Machine Learning Research (TMLR), May 2025. arXiv 2407.01502 (first posted July 1, 2024). arXiv · OpenReview (TMLR) · reference [3]
It is a reality check. It asks if the agent results you read about are real, useful and repeatable. It will make you a better reader of every other agent paper in this course.
Reading tip: you can skip most of the appendices. The tables and figures in the main text are the key evidence.
Schluntz and Zhang (Anthropic Engineering), December 19, 2024. Read online · reference [4]. The course also assigns it in Week 4 [8].
Why: It is the source for the workflow-versus-agent line and the five workflow patterns used in these notes.
Think about: Pick one pattern. Describe a task from your own work that fits it. Then say what would have to be true for you to upgrade it to an agent.
Yao, Zhao, Yu, Du, Shafran, Narasimhan, Cao. ICLR 2023. arXiv 2210.03629 · reference [5]. The course also assigns it in Week 4 [8].
Why: The Thought, Action, Observation pattern is the root of the loop you build in the lab. Read the introduction, section 2 and the failure analysis in section 3.
Think about: In the paper's tests, ReAct beat chain of thought on fact checking (FEVER) but slightly trailed it on HotpotQA. Why might grounding help one task and hurt the other?
Sumers, Yao, Narasimhan, Griffiths. TMLR 2024. arXiv 2309.02427 · reference [6]. The course assigns it in Week 4 [8].
Why: It gives a precise vocabulary for memory, actions and decision-making, and connects LLM agents to older AI work. The authors say readers who care about practical design can focus on sections 4 to 6.
Think about: Describe the lab agent in CoALA terms. What is its working memory? Does it have any long-term memory? What are its internal and external actions?
Russell and Norvig. Book website · reference [7]. The site lists the 4th US edition, with Chapter 2 starting on page 36.
Why: It is the source of the textbook meaning of "agent" and a good base for thinking about environments and rational behavior.
Think about: Under this definition, is a spam filter an agent? Is a recommender system? What extra properties would you need before calling a system "agentic"?
Time: about 90 minutes. Goal: build the smallest real agent. It reads a question, picks a tool, runs it, reads the result, and answers. You do not need an API key. A mock model stands in for the LLM.
for loop with a model call, a tool call and a stop rule.agent.py. Or download it: agent.py.test_agent.py in the same folder. Or download: test_agent.py. The test code is listed after the lab exercises.agent.py"""A minimal agent loop. Standard library only. Python 3.9+.
Run with the mock model (no API key needed):
python agent.py "What is (12 + 8) * 3?"
Run with a real model (any OpenAI-compatible chat API):
export OPENAI_API_KEY=... # your key
export LLM_MODEL=... # a model name your provider offers
export LLM_BASE_URL=https://api.openai.com/v1 # optional
python agent.py --real "What is (12 + 8) * 3?"
"""
import ast
import json
import operator
import os
import re
import sys
import urllib.request
# ---------- 1. Tools: plain Python functions plus a short description ----------
_OPS = {ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul,
ast.Div: operator.truediv, ast.Pow: operator.pow, ast.USub: operator.neg}
def _eval(node):
if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
return node.value
if isinstance(node, ast.BinOp) and type(node.op) in _OPS:
return _OPS[type(node.op)](_eval(node.left), _eval(node.right))
if isinstance(node, ast.UnaryOp) and type(node.op) in _OPS:
return _OPS[type(node.op)](_eval(node.operand))
raise ValueError("unsupported expression")
def calculator(expression: str) -> str:
"""Safely evaluate basic arithmetic such as '(12 + 8) * 3'."""
tree = ast.parse(expression, mode="eval")
return str(_eval(tree.body))
FACTS = {
"react": "ReAct (2022) mixes reasoning steps and tool actions in one loop.",
"compound ai system": "A system that uses several parts: model calls, retrievers, tools.",
"workflow": "LLMs and tools are run along a path the developer wrote in code.",
"agent": "The LLM decides its own next step and which tool to use.",
}
def lookup(term: str) -> str:
"""Look up a short definition in a tiny local knowledge base."""
key = term.strip().lower()
if key in FACTS:
return FACTS[key]
raise KeyError(f"no entry for '{term}'. Known terms: {', '.join(FACTS)}")
TOOLS = {
"calculator": {"fn": calculator, "args": ["expression"],
"doc": "Evaluate basic arithmetic."},
"lookup": {"fn": lookup, "args": ["term"],
"doc": "Get a short definition of a term."},
}
# ---------- 2. The model: any object with .complete(messages) -> str ----------
# The model must answer with JSON, in one of two shapes:
# {"thought": "...", "action": "calculator", "input": {"expression": "2+2"}}
# {"thought": "...", "final": "The answer is 4"}
def system_prompt() -> str:
lines = ["You are an agent. Think, then act. Reply with ONE JSON object only.",
'To use a tool: {"thought": "...", "action": "<tool>", "input": {...}}',
'To finish: {"thought": "...", "final": "<answer>"}',
"Tools:"]
for name, t in TOOLS.items():
lines.append(f"- {name}({', '.join(t['args'])}): {t['doc']}")
return "\n".join(lines)
class MockLLM:
"""A rule-based stand-in for a real model. It lets the loop run offline.
It is NOT smart. It only shows the shape of the conversation."""
def complete(self, messages):
last = messages[-1]
if last["role"] == "user":
question = last["content"]
expr = re.search(r"[\d(][\d\s+\-*/().^]*[\d)]", question)
if expr and any(c in expr.group(0) for c in "+-*/^"):
return json.dumps({"thought": "This is arithmetic. I will use the calculator.",
"action": "calculator",
"input": {"expression": expr.group(0).replace("^", "**")}})
m = re.search(r"(?:what is|define|explain)\s+(?:a |an |the )?([a-z\- ]+?)\??$",
question.strip().lower())
if m:
return json.dumps({"thought": "I need a definition. I will look it up.",
"action": "lookup", "input": {"term": m.group(1)}})
return json.dumps({"thought": "No tool fits.", "final": "I cannot help with that."})
# last message is a tool observation
obs = last["content"]
if obs.startswith("ERROR"):
return json.dumps({"thought": "The tool failed. I will report it.",
"final": f"Sorry, the tool failed. {obs}"})
return json.dumps({"thought": "I have what I need.", "final": obs})
class OpenAICompatibleLLM:
"""Calls any chat-completions API that follows the OpenAI format."""
def __init__(self):
self.key = os.environ["OPENAI_API_KEY"]
self.model = os.environ["LLM_MODEL"]
self.base = os.environ.get("LLM_BASE_URL", "https://api.openai.com/v1")
def complete(self, messages):
body = json.dumps({"model": self.model, "messages": messages,
"temperature": 0}).encode()
req = urllib.request.Request(
self.base + "/chat/completions", data=body,
headers={"Content-Type": "application/json",
"Authorization": "Bearer " + self.key})
with urllib.request.urlopen(req, timeout=60) as r:
return json.load(r)["choices"][0]["message"]["content"]
# ---------- 3. The loop ----------
def run_agent(question, llm, max_steps=5, verbose=True):
messages = [{"role": "system", "content": system_prompt()},
{"role": "user", "content": question}]
for step in range(1, max_steps + 1):
raw = llm.complete(messages)
messages.append({"role": "assistant", "content": raw})
try:
msg = json.loads(raw)
except json.JSONDecodeError:
obs = "ERROR: reply was not valid JSON. Reply with one JSON object."
messages.append({"role": "tool", "content": obs})
if verbose: print(f"[{step}] bad JSON -> asking again")
continue
if verbose: print(f"[{step}] thought: {msg.get('thought', '')}")
if "final" in msg:
if verbose: print(f"[{step}] final: {msg['final']}")
return msg["final"]
name, args = msg.get("action"), msg.get("input", {})
if name not in TOOLS:
obs = f"ERROR: unknown tool '{name}'. Tools: {', '.join(TOOLS)}"
else:
try:
obs = TOOLS[name]["fn"](**args)
except Exception as e: # tool errors go back to the model
obs = f"ERROR: {type(e).__name__}: {e}"
if verbose: print(f"[{step}] action: {name}({args}) -> {obs}")
messages.append({"role": "tool", "content": obs})
return "Stopped: step limit reached."
if __name__ == "__main__":
argv = sys.argv[1:]
real = "--real" in argv
argv = [a for a in argv if a != "--real"]
q = " ".join(argv) or "What is (12 + 8) * 3?"
run_agent(q, OpenAICompatibleLLM() if real else MockLLM())
$ python agent.py "What is (12 + 8) * 3?"
[1] thought: This is arithmetic. I will use the calculator.
[1] action: calculator({'expression': '(12 + 8) * 3'}) -> 60
[2] thought: I have what I need.
[2] final: 60
$ python agent.py "What is a workflow?"
[1] thought: I need a definition. I will look it up.
[1] action: lookup({'term': 'workflow'}) -> LLMs and tools are run along a path the developer wrote in code.
[2] thought: I have what I need.
[2] final: LLMs and tools are run along a path the developer wrote in code.
TestedI ran this code with Python 3.13 on October 28, 2026. Both demo runs printed the output shown above. All nine unit tests passed.
TOOLS dictionary is the agent's menu. The calculator uses ast to parse the math. It does not use eval. The model's output is untrusted input, so never run it as code.complete(messages) method works. MockLLM uses simple rules. OpenAICompatibleLLM calls a real chat API. The model must reply with JSON: either an action or a final answer.run_agent asks the model, parses the reply, runs the tool, and adds the result to the messages. It stops on a final answer or after max_steps. Tool errors are sent back to the model as text. They do not crash the program.Honest note about the mockMockLLM is not smart. It matches patterns with regular expressions. It exists so that you can see the shape of an agent run, and test your loop, without any account or cost. The loop and tools are the real thing. Only the "brain" is fake.
Any service with an OpenAI-style chat API should work. I tested only the mock path on the box. Set three variables, then add --real:
export OPENAI_API_KEY="your key"
export LLM_MODEL="a model name your provider offers"
export LLM_BASE_URL="https://api.openai.com/v1" # change for other providers
python agent.py --real "What is (12 + 8) * 3?"
Real models sometimes wrap JSON in extra text or code fences. If that happens, the loop sends "bad JSON" back and tries again. A good extension is to make the parser more forgiving.
python agent.py "What is 1/0?". Which line of the loop catches the error? What does the model see?word_count(text) to TOOLS. Update MockLLM so it can choose it for a question like "How many words are in 'to be or not to be'?". Add a test.Scripted model that always asks for a tool. Check that the loop stops. Why is this stop rule the most important safety feature in the file?MockLLM?test_agent.pyimport unittest
from agent import calculator, lookup, run_agent, MockLLM
class Scripted:
"""Plays back fixed replies, so we can test the loop itself."""
def __init__(self, replies): self.replies = list(replies)
def complete(self, messages): return self.replies.pop(0)
class Tests(unittest.TestCase):
def test_calculator(self):
self.assertEqual(calculator("(12 + 8) * 3"), "60")
def test_calculator_blocks_code(self):
with self.assertRaises(Exception):
calculator("__import__('os').system('echo hi')")
def test_lookup_missing(self):
with self.assertRaises(KeyError): lookup("banana")
def test_mock_math(self):
self.assertEqual(run_agent("What is (12 + 8) * 3?", MockLLM(), verbose=False), "60")
def test_mock_lookup(self):
out = run_agent("What is a workflow?", MockLLM(), verbose=False)
self.assertIn("path the developer wrote", out)
def test_unknown_tool_is_reported_not_crashed(self):
llm = Scripted(['{"action": "email", "input": {}}', '{"final": "ok"}'])
self.assertEqual(run_agent("hi", llm, verbose=False), "ok")
def test_bad_json_retry(self):
llm = Scripted(["not json", '{"final": "done"}'])
self.assertEqual(run_agent("hi", llm, verbose=False), "done")
def test_step_limit(self):
llm = Scripted(['{"action": "calculator", "input": {"expression": "1+1"}}'] * 3)
self.assertEqual(run_agent("hi", llm, max_steps=3, verbose=False),
"Stopped: step limit reached.")
def test_tool_error_goes_back_to_model(self):
llm = Scripted(['{"action": "calculator", "input": {"expression": "1/0"}}',
'{"final": "handled"}'])
self.assertEqual(run_agent("hi", llm, verbose=False), "handled")
if __name__ == "__main__":
unittest.main(verbosity=2)
$ python test_agent.py
test_bad_json_retry (__main__.Tests.test_bad_json_retry) ... ok
test_calculator (__main__.Tests.test_calculator) ... ok
test_calculator_blocks_code (__main__.Tests.test_calculator_blocks_code) ... ok
test_lookup_missing (__main__.Tests.test_lookup_missing) ... ok
test_mock_lookup (__main__.Tests.test_mock_lookup) ... ok
test_mock_math (__main__.Tests.test_mock_math) ... ok
test_step_limit (__main__.Tests.test_step_limit) ... ok
test_tool_error_goes_back_to_model (__main__.Tests.test_tool_error_goes_back_to_model) ... ok
test_unknown_tool_is_reported_not_crashed (__main__.Tests.test_unknown_tool_is_reported_not_crashed) ... ok
----------------------------------------------------------------------
Ran 9 tests in 0.001s
OK
The tests use a Scripted model that plays back fixed replies. That is the trick for testing agents: replace the unpredictable part with a predictable one, and test the loop around it.
Use these in a study group or a class. Try to answer with an example and a source. Give each about 5 to 10 minutes.
Pick one answer for each question, then press Check answers.
ast instead of calling eval?
eval.eval cannot do addition.eval could run arbitrary code.B. The post defines a compound AI system as one that tackles AI tasks using multiple interacting components, including multiple model calls, retrievers, or external tools. A plain model, by contrast, is just a statistical model [1].
D. Workflows are "orchestrated through predefined code paths". In agents, LLMs "dynamically direct their own processes and tool usage" [4]. Both kinds can use tools. Cost and model size are not the defining difference.
A. Planning (subgoals and reflection), memory (short-term and long-term), and tool use [2].
C. ReAct widens the action space to include language. A thought "does not affect the external environment, thus leading to no observation feedback". It updates the context to help later reasoning or acting [5].
D. Procedural memory holds implicit knowledge in the model weights and explicit knowledge in the agent's code [6]. Working memory is the current context. Episodic is past experience. Semantic is facts about the world.
B. There was no significant accuracy difference between their warming baseline and the best complex agent on HumanEval, and for substantially similar accuracy the cost could differ by almost two orders of magnitude [3].
C. Calling a model many times can lift accuracy, so a leaderboard that only shows accuracy can reward needless cost and hide whether a design is truly better [3].
A. Traditional AI defines agents as entities that perceive and act on their environment. Kapoor et al. note that a thermostat qualifies under that definition, and that the LLM-era use of the word is narrower [3] [7].
C. 0.9510 is about 0.60. This is my own arithmetic, used to illustrate Anthropic's warning about compounding errors [4]. Real steps are rarely fully independent, so treat the number as a rough guide.
D. Model output is untrusted. eval would execute any Python it was given. Parsing with ast and allowing only a few safe operations keeps the tool limited to math. This echoes CoALA's point that the action space carries safety risks [6].
Scoring: 9 to 10 means you are ready for Week 2. 7 to 8: re-read the sections linked in the answers. Below 7: redo the reading guide questions first. When you print this page, check the quiz first if you want your marks on the paper copy. The answer key is included when you print.
Title: Workflow or agent? Build, measure, decide.
Time: 1 to 2 hours. Total: 100 points. Work: solo.
Extend the lab code and write a short memo (one to two pages). You may use the mock model. You may also use a real model if you have a key.
For each of the three scenarios below, say whether you would build a single call, a workflow (name the pattern from [4]), or an agent. Give two or three sentences of reasons. Note one risk per scenario.
agent.py (or your own file name) and your tests.| Criterion | Full marks | Partial | Points |
|---|---|---|---|
| A. New tool and tests | Tool works. Three or more tests plus an error case pass. The model can choose the tool. Code is clear. | Tool works, but tests are thin or the model cannot choose it reliably. | 30 |
| B. Measurement | Eight good questions. Both versions run. Table has accuracy and model calls. The pick is justified using cost and accuracy. | Table is missing calls, or the pick has no reasoning. | 30 |
| C. Design memo | Three sensible choices, each tied to a named pattern or to the agent definition, with a stated risk. | Choices are right, but reasons are vague or risks are missing. | 25 |
| D. Safety and honesty | Three realistic failure modes with guards. Limits of the tests are stated plainly. | Failure modes are generic, or limits are not stated. | 15 |
| Total | 100 | ||
Grade bands: 90 to 100 excellent. 75 to 89 good. 60 to 74 needs work. Under 60: redo and resubmit. Plain writing is rewarded: short sentences, no filler.
| Term | Meaning |
|---|---|
| Action | Something the agent does. External actions affect the environment (call a tool). Internal actions affect its own memory or thinking [6]. |
| Agent | In the classic sense, an entity that perceives its environment and acts on it [7]. In LLM work, a system where the model directs its own process and tool use [4]. |
| Agent-computer interface (ACI) | The way tools and their descriptions are presented to an agent. Anthropic says it deserves as much care as a human interface [4]. |
| Agentic system | Anthropic's umbrella term for both workflows and agents [4]. Kapoor et al. treat "agentic" as a range [3]. |
| Compound AI system | A system that uses several interacting parts, such as model calls, retrievers and tools [1]. |
| Context window | The amount of text the model can read in one call. It limits how much history and tool output fits [2]. |
| Cost-controlled evaluation | Comparing agents on accuracy and cost together, for example with a Pareto curve [3]. |
| DSPy | A framework that tunes the prompts and examples of a multi-step LLM pipeline to maximize a metric [1]. |
| Environment | Everything outside the agent that it can sense or change: web, files, people, APIs [6]. |
| Episodic memory | Memory of past events and runs [6]. |
| Grounding | Connecting the model to real information or actions outside itself, such as tool results. CoALA calls external actions "grounding actions" [6]. |
| Hallucination | When a model states something that is not true or not supported. Retrieval and tools can reduce it [5] [1]. |
| Holdout set | Test data kept apart from what developers tune on, so results show real skill and not memorized shortcuts [3]. |
| Long-term memory | Information kept outside the context window and fetched when needed [2]. |
| Observation | The result an agent sees after an action, such as a tool's output [5]. |
| Orchestrator-workers | A workflow in which a central LLM splits a task, hands parts to workers and merges results [4]. |
| Pareto frontier | The set of designs where you cannot improve one measure (like accuracy) without hurting another (like cost) [3]. |
| Procedural memory | Knowledge of how to act: model weights and the agent's code [6]. |
| Prompt chaining | A workflow of fixed steps where each model call uses the previous output [4]. |
| ReAct | A pattern that interleaves reasoning steps ("thoughts") with actions and observations [5]. |
| Retrieval-augmented generation (RAG) | Searching a data source first, then having the model answer using what was found [1]. |
| Routing | A workflow that classifies an input and sends it to a specialized path [4]. |
| Semantic memory | Facts about the world and about the agent itself [6]. |
| Stopping condition | A rule that ends an agent run, such as a final answer or a maximum number of steps [4]. |
| Tool | A function or service the model can ask the program to run, such as search, a calculator or an API [2]. |
| Trace | The recorded list of steps, tool calls and results from one run. It is the main thing you read when you debug [1]. |
| Workflow | A system where LLMs and tools follow predefined code paths [4]. |
| Working memory | The information active in the current step: goal, recent inputs, results of thinking [6]. |
All links were opened and checked on October 28, 2026. Items 1 to 3 are the required readings for this week.
About the sourcesEvery claim about a source in these notes comes from that source's own page, which I opened while writing. Where a number is my own arithmetic, the text says so. Where the source gives a made-up example, the text says that too. I did not read the two books in full. I did not use the lecture slides, and this pack does not reproduce them. If you find a mistake, please tell the author.