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.

Chapter 3: Tools and the Autonomy Dial

{"pick": null, "reason": "Paper 0 might use retrieval, but its abstract never
 says how answers are improved, so I cannot tell from what I was given."}

That’s where Chapter 2 stopped, and the reply is fair. The abstract of Better Answers with Less Compute really doesn’t say how the answers get better. A person would open the paper. The model can’t, because the only text it ever sees is what we pasted in before it started.

So this chapter gives it a short list of things it may ask for: show me the abstract of paper 0, show me its full text. The code carries out the request and hands the result back. That brings back the loop from Chapter 1, except that now the model picks each step.

Once a program can take actions, I also have to decide how much it may do without asking me. That’s the second half of this chapter.

Chapter 3 of 12 · Foundations

Where we left off: The model judges papers by meaning, but it can only see what we paste into its prompt, and it can’t ask for more.

What we fix now: Give the model tools it can ask for, run them in code, feed the results back into the loop, and then decide how much the scout may do on its own.

By the end, you can:

  • explain what a tool is, from the model’s side and from the code’s side

  • build a scout that chooses its own next step: read an abstract, read the full text, or make a decision

  • describe three levels of autonomy, and see why one good run doesn’t tell you which level is safe

The fix: tools the model can ask for

A tool is a Python function plus a one-line description. The two halves live in different places:

  • The model only sees the name and the description, for example “read_full_text: show the full text of a paper; use it when the abstract is not enough”. It can’t run anything. It can only propose “use read_full_text on paper 0”.

  • Your code holds the actual function. When the model proposes a tool call, your code checks it, runs the function, and pastes the result into the next prompt.

That pasted result is the observe step from Chapter 1:

Function-calling APIs can make it look as if the model runs the tool itself. It doesn’t. Some library code on your side runs it, and I’d rather that code be mine, where I can see and limit it. The Colab bonus at the end shows the built-in version, and the call still goes through code I wrote.

There’s a practical win too. The prompt now only needs titles. The model pulls in the abstract or full text of the few papers that look promising, which is what makes a day with a hundred-plus papers workable.

Everything the model knows about its abilities is in that “Actions you can take” list. Now the loop that runs it:

Read the trace top to bottom. The model looks at the abstract, still can’t tell, asks for the full text, and only then decides. The full text says the method retrieves Wikipedia passages before answering, so this is a RAG paper, and the scout recommends it. In Chapter 2 this paper was a dead end.

Every result goes into transcript, which is pasted into the next prompt. That’s the scout’s whole memory within a run; there’s nothing cleverer behind it. parse_action is Chapter 2’s check, grown up: an unknown action or a paper that doesn’t exist becomes an error message the model reads on its next step, instead of a crash.

The autonomy dial

So far the scout only reads, and reading can’t hurt anything. What I actually want from it is to do something with its decision, like writing a short summary for my blog’s reading list. Other people would see that.

Before adding a publish_summary action, I need to decide how much the scout may do on its own. I think of it as a dial with three settings:

SettingThe scout...You...A wrong decision costs
suggest (v1)recommends a paperdecide everythinga few seconds of your time
draft (v2)writes a summary and asks to publish itapprove or reject each onea moment of reading
act (v3)publishes on its owncheck later, if at alla wrong post on your blog

The model is identical at all three settings. What moves is where I stand in the loop, and so how far a mistake gets before someone catches it.

Same run, same decision, three endings. At "suggest" the output is a note to you. At "draft" the scout does the writing, but nothing goes out without a yes. At "act" it goes straight onto the blog.

On day 5 the decision was right, so "act" looks great: a correct post and no work. One good run is exactly what makes turning the dial up so tempting.

The scout saw “retrieving” in the abstract, skipped the full text, and published a summary of an education study on an AI blog. At "suggest" this would have cost five seconds: read the title, shrug, move on. At "act" it’s public.

Day 5 went perfectly and day 6 went wrong, with the same model, the same code and the same prompt. Watching a run or two tells you nothing about how often the scout is right. I don’t want it to get more autonomy because a few examples looked good. It should earn each step on the dial through repeated measurement: build it for one setting, measure how often it’s right, keep checking it on real use, and only then move it up.

The rest of the course is that process. I use a framework called CC/CD for it, Continuous Development and Continuous Calibration, from an article by Aishwarya Reganti and Kiriti Badam. Chapter 4 starts the first half.

Bonus (Colab only): a real model with tools

Open this notebook in Colab to let a real model choose the actions:

Open In Colab

Get a free key at aistudio.google.com/apikey (no credit card needed), then paste it into API_KEY below. Treat it like a password: fine in your own private Colab copy while experimenting, never in a public repository or notebook.

The first cell runs the scout from this chapter with a real model. The second shows the same job with Gemini’s built-in function calling.

Look at which tools the real model asks for, and in what order. Does it read the full text on day 6, or does it fall for “retrieval” the way the stand-in did? Run it a few times and see whether it stays the same.

The cell below does the same job with native function calling. Instead of describing the actions in the prompt and parsing JSON by hand, you pass Python functions as tools, and the model returns structured tool calls. I switch off the library’s option to run those calls automatically, so my loop still decides what actually runs, and checks the paper number first.

Quick check

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

  1. What does the model actually “see” of a tool, and what does your code hold? Why does that split matter?

Check your reasoning ▸

A strong answer says the model only sees the tool’s name and description, and can only propose a call to it. The code holds the real function and decides whether to run it. That split means nothing happens in the world unless your code carries it out, which is also where you can check, refuse, or limit a request.

  1. The Chapter 3 prompt lists only paper titles. Why is that better than pasting every abstract, as in Chapter 2?

Check your reasoning ▸

A good answer mentions scale: a real day can have hundreds of papers, and pasting every abstract and full text won’t fit or will be slow and costly. With tools, the model pulls in details only for the papers that look promising, so the prompt stays small.

  1. What would go wrong if run_scout didn’t append each result to transcript?

Check your reasoning ▸

The model would never see the result of its own actions. It would ask for the same abstract again and again, because as far as its prompt shows, nothing has happened yet. The transcript is the observe step: it’s how information from one step reaches the next “think”.

  1. On day 6, the scout made the same wrong decision at every dial setting. What actually differed between “suggest” and “act”?

Check your reasoning ▸

Only where the mistake ended up. At “suggest” it’s a bad suggestion you can ignore in seconds; at “draft” it’s a draft you’d reject; at “act” it’s a public post. A strong answer notes that the dial leaves the error rate alone. It changes how much each mistake costs and who catches it.

  1. After day 5, would you have set the dial to “act”? What evidence would you want before doing that?

Check your reasoning ▸

A good answer says one run is an anecdote, not evidence. You’d want to see the scout’s decisions on many papers where you already know the right answer, and a number for how often it’s right, plus some idea of what kinds of mistakes it makes. The next three chapters build that: a scope, labeled data, and an evaluation.


You can now: give a model tools it can ask for, run them safely in code, feed results back into the loop, and explain what the autonomy dial changes and what it doesn’t.

But one problem remains: one good run told us nothing about the next one, and we have no way to know when the scout has earned more autonomy. The next chapter starts building on purpose: pick the narrowest useful version of the scout, write down exactly what it should do, and create examples with known right answers to measure it against.

Next → Chapter 4: Scope and Curate Data