Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Every week I pick one new paper for Vector Reads, and every week the hard part isn’t reading it. It’s finding it. arXiv posts well over a hundred new language and retrieval papers on a normal weekday, and most of them have nothing to do with what I care about.

So the obvious first move is a script: fetch today’s papers, pick the one that best matches my interest, summarize it. That works fine on a good day. On a bad day, when nothing new matches, it still picks a paper (picking is step two) and still summarizes it (summarizing is step three), and the summary looks exactly as confident as on a good day. The script did what I told it. I just told it the same thing no matter what it found.

This whole course grows that script into something better, one failure at a time.

Chapter 1 of 12 · Foundations

Where we left off: Nowhere yet, this is the first chapter. Nothing to leave behind.

What we fix now: See why a script with fixed steps breaks when its results surprise it, and build the simplest possible program that looks at what it found before deciding what to do next.

By the end, you can:

  • explain the difference between a fixed pipeline and an agent loop

  • build a paper scout that observes, decides, and acts, step by step

  • identify exactly why hand-written decision rules stop working as new situations show up

The fix: look before you take the next step

A fixed pipeline decides everything in advance: fetch, pick, summarize, in that order, every time. An agent changes one thing. After each step it looks at what happened and decides what to do next. Three moves, repeated:

  1. Think: look at everything gathered so far and choose the next step.

  2. Act: do that one step, like running a search.

  3. Observe: take the result back in, so the next “think” can use it.

The loop keeps going until the agent decides it’s done, or until it runs out of allowed steps.

In the pipeline, every decision was made by me, before the script saw a single paper. In the loop, some of the deciding happens during the run, after the program has seen what’s actually there. That shift, from the author deciding everything up front to the program deciding some of it as it goes, is what I mean by “agent” in this course. There are fancier definitions around; this one is enough to build on.

Three steps, always in the same order, and on day 1 that’s all you need. The best paper really is the best paper.

Every paper scores zero, so max just returns the first one in the list. The scout summarizes a paper on mixture-of-experts, with the same confidence as on day 1. The only hint is “score 0”, and nothing in the script reacts to it.

Two things went wrong at once. It picked a paper I don’t care about, and it walked straight past the one I do, because “RAG” isn’t the word “retrieval”. A person would have tried another word, or said “nothing today”. The script can’t: its next step was fixed before it saw the results.

The same scout, as a loop

Split the scout into small actions, and put a decide function in charge of choosing the next one after every step. For now, decide is a plain list of rules written by hand:

  • if the last search found something, summarize the top result and stop

  • otherwise, if there’s a keyword we haven’t tried yet, search for it

  • otherwise, stop and say that nothing matched

I’m keeping decide deliberately dumb here. A smarter rule list would hide the problem this chapter is about.

decide is the think step, running a search or a summary is the act step, and storing the result in state is the observe step. max_steps is a safety limit, so the loop can’t run forever.

Run it on day 2, then try day_1 and the empty day_3.

Read the printed steps top to bottom. The first search comes back empty, and instead of pressing on, the loop tries the next keyword. “rag” finds the right paper, so it summarizes and stops. On day_3, all three searches come back empty and the scout says so, instead of summarizing a weather paper nobody asked about.

The scout summarizes the architecture search paper and never touches the one I wanted. Both mistakes have the same cause: the rules match words. “Search” in “architecture search” has nothing to do with searching documents, and “grounding” and “fetched passages” aren’t in the keyword list at all.

You could patch it: add “grounding”, skip titles with “architecture”. Then a relevant paper about a new retrieval architecture shows up and gets skipped, or one says “evidence-backed generation” and gets missed, and you’re patching again. Every new kind of paper needs a new rule, written before the paper exists. The loop itself is fine. What’s doing the deciding is too rigid.

Quick check

Before moving on, answer for yourself (no peeking ahead):

  1. In your own words, what’s the difference between the fixed scout and the loop scout? Where does the decision about the next step get made in each?

Check your reasoning ▸

A strong answer says the fixed scout’s steps are all decided in advance by whoever wrote it, so it runs the same three steps no matter what it finds, while the loop scout decides its next step during the run, after looking at the result of the previous one. What matters is when: before seeing the papers, or after.

  1. On day 2, the fixed scout printed “score 0” next to the paper it picked. Why didn’t that stop it, and what would a sensible reaction to that score have been?

Check your reasoning ▸

A good answer points out that nothing in the fixed script reads the score after picking; summarizing is simply the next step. A sensible reaction would be to try a different keyword or to report that nothing matched, which is exactly what the loop version does once the decision can depend on what was observed.

  1. In run_scout, which line is the “think” step, which is “act”, and which is “observe”? What would happen if you deleted the “observe” line?

Check your reasoning ▸

decide(state) is think, search(papers, arg) is act, and updating state is observe. Without the observe step, decide would never see new results or know which keywords were tried, so it would make the same choice every time: the loop would run, but it would stop being able to change its mind.

  1. Set keywords = ["weather"] and run the loop on day_2. Then imagine decide had a bug and always returned "search". What does max_steps protect you from?

Check your reasoning ▸

With ["weather"] on day 2, one empty search and the scout stops honestly. With an always-search bug, the loop would never reach a stop, and without max_steps it would run forever. A strong answer adds that in a real agent every step can cost time and money (a model call, an API request), so a step limit is a basic safety feature, not an afterthought.

  1. Write one new rule for decide that fixes day 4. Then describe a paper, real or made up, that your new rule would get wrong.

Check your reasoning ▸

Any rule works as a starting point, like adding “grounding” to the keywords or skipping titles with “architecture”. The important part is the second half: a good answer finds a paper that breaks the new rule, such as a relevant paper about a new retrieval architecture, or one that talks about “citing sources” without the word “grounding”. Hand-written rules can always be broken by the next paper nobody anticipated.


You can now: explain the difference between a fixed pipeline and an agent loop, and you’ve built a scout that decides its next step after seeing what it found.

But one problem remains: the decisions come from rules we wrote in advance, and they match words, not topics. Every new kind of paper needs a new rule. The next chapter hands the “think” step to a language model, which can judge whether a paper is relevant from what it actually says.

Next → Chapter 2: Letting a Model Decide