Lesson 10
Can a model do things, not just talk?
A model only writes text. Your app can give it tools, like a weather service or a train booking system, and run them when the model asks. This lesson shows how that works, and why a model sometimes makes things up.
1Can a model do things, or only write text?
A model only writes text. By itself, it cannot check today's weather, send an email or book a ticket.
- ๐ฆ๏ธIt has no live data. Everything it knows comes from the text it read in training (lesson 2). Ask "What's the weather in Delhi right now?" With no help, it can only guess from old text about Delhi.
- ๐งIt cannot act. It only writes words. Ask it to email your manager. It writes the email, but the email stays in the chat. Nothing is sent.
- ๐งฎIt does not calculate. It writes digits that have a high chance of coming next, one token at a time (lessons 1 and 6). A drawing in one book shows a model asked to calculate 47 รท 12 ร 3.14. It answers 7.34. The right answer is 12.2983.
To check, send or calculate anything, the model needs help from your code.
2What is tool calling?
Tool calling is how a model asks your app to run a tool for it.
The model never runs anything itself. Your code does.
It works in five steps:
- Your app tells the model which tools exist: each tool's name, what it does, and what it needs.
- When a tool would help, the model writes a tool request instead of an answer.
- Your code runs the tool.
- Your app sends the result to the model.
- The model reads the result and writes the answer.
The messages are written in JSON, a plain-text format of names and values inside curly brackets. Example: one weather question, from your question to the answer. Use the buttons to go through it one step at a time.
- ๐ง You
- ๐งโ๐ป Your app
- ๐ค LLM
- ๐ฆ๏ธ Weather service
YOU โ YOUR APP โ LLM
๐ง Step 1: you ask, and your app adds the tool list
Who: ๐ง you type the question. ๐งโ๐ป Your app sends it to the LLM, with the list of tools it has.
What's the weather in Delhi right now?
What your app sends (simplified):{
"tools": [{
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}],
"messages": [{
"role": "user",
"content": "What's the weather in Delhi right now?"
}]
}
LLM โ YOUR APP
๐ค Step 2: the LLM asks for the tool
Who: ๐ค the LLM. It writes a tool request instead of an answer. Nothing has run yet.
{
"stop_reason": "tool_use",
"content": [{
"type": "tool_use",
"id": "toolu_abc123",
"name": "get_weather",
"input": {
"location": "Delhi"
}
}]
}
"stop_reason": "tool_use" tells your app: I stopped because I want a tool.
YOUR APP โ WEATHER SERVICE
๐ฆ๏ธ Step 3: your app runs the tool
Who: ๐งโ๐ป your app reads the name and the input, then calls ๐ฆ๏ธ the weather service.
get_weather("Delhi")โ ๐ฆ๏ธ โ"31ยฐC, haze"This is ordinary code you wrote, like any call to a web service. The LLM is not involved in this step.
YOUR APP โ LLM
๐งโ๐ป Step 4: your app sends the result to the LLM
Who: ๐งโ๐ป your app. It sends the whole chat again, because the model remembers nothing between messages (lesson 8). The result goes at the end.
"messages": [
(your question, step 1),
(the tool request, step 2),
{"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "31ยฐC, haze"
}]}
]
The same id, toolu_abc123, shows which request this result answers.
LLM โ YOUR APP
๐ค Step 5: the LLM writes the answer
Who: ๐ค the LLM. It reads "31ยฐC, haze" in its prompt and writes a normal reply.
{
"stop_reason": "end_turn",
"content": [{
"type": "text",
"text": "It's 31ยฐC and hazy in Delhi right now."
}]
}
"end_turn" means: I am done, no more tools.
YOUR APP โ YOU
๐ง Step 6: you see the answer
Who: ๐งโ๐ป your app shows the text to ๐ง you. You never see the JSON.
It's 31ยฐC and hazy in Delhi right now.
A made-up question, weather and id. The JSON follows the shapes of Anthropic's Claude API, simplified: fields such as the model name are not shown, and the city field's description is cut. Each step says who does the work. Those workers are dark in the row at the top. Your question is in a white bubble, and the reply you see is in a green one.
Three things to know about tool calling:
- ๐A tool request is only text in a fixed shape, like a filled-in form.
"input": {"location": "Delhi"}is just characters. When the model writes it, no weather service has been called. - ๐งโ๐ปYour code reads the request and decides whether to run it. It can refuse a tool, or ask you before it sends an email.
- ๐The result goes into the prompt as text. Your app pastes "31ยฐC, haze" into the prompt, the same way RAG pasted chunks of the PDF (lesson 9).
A tool also fixes the maths question from section 1. In the same drawing in the book, the model is given a calculator tool, and it answers 12.2983, which is right.
3What is an agent?
An agent is an LLM with tools, running in a loop until a goal is done.
Take one goal: "Book the cheapest train from Mumbai to Pune tomorrow." One tool can't do it. It needs a search, a comparison and a booking, in that order.
Each round of the loop has three parts:
- ๐ญThink: the model decides the next step.
- ๐ ๏ธAct: the model asks for a tool, and your app runs it. This is the tool calling from section 2.
- ๐Look: the model reads the result that your app put in the prompt.
Your app can also add its own check between Act and Look. Round 3 below shows one.
When the loop continues, and when it stops:
- ๐The model starts a new round as long as it asks for a tool.
- ๐The loop stops when the model writes a normal answer instead of a tool request.
Example: the train goal, round by round. Use the buttons to go through it one step at a time.
- ๐ง You
- ๐งโ๐ป Your app
- ๐ค LLM
- ๐ Train search
- ๐ซ Booking
THE GOAL
๐ง Step 1: you give a goal
Who: ๐ง you ask. ๐งโ๐ป Your app sends it to ๐ค the LLM, with three tools: search_trains, check_seats and book_ticket.
Book the cheapest train from Mumbai to Pune tomorrow.
THE LOOP ยท ROUND 1 OF 3
๐ Round 1: find the trains
Who: ๐ค the LLM asks, ๐งโ๐ป your app runs ๐ the train search, and puts the result in the prompt.
search_trains({"from": "Mumbai", "to": "Pune", "date": "tomorrow"})
๐ LookTrain A 07:10 โน240 ยท Train B 11:30 โน185 ยท Train C 17:45 โน310
THE LOOP ยท ROUND 2 OF 3
๐ Round 2: compare, then check seats
Who: ๐ค the LLM compares the prices and asks for one more tool. ๐งโ๐ป Your app runs it.
check_seats({"train": "B"})
๐ Look12 seats free
THE LOOP ยท ROUND 3 OF 3
๐ Round 3: book, after you say yes
Who: ๐ค the LLM asks to book. ๐งโ๐ป Your app checks with ๐ง you first, then runs ๐ซ the booking.
book_ticket({"train": "B"})
๐ AskYour app, before it runs the booking: "Book Train B, 11:30, for โน185?" You: "Yes."
๐ LookBooked. PNR 4821937
DONE
๐ Step 5: the LLM stops asking for tools
Who: ๐ค the LLM writes a normal reply. ๐งโ๐ป Your app sees no tool request, so the loop ends, and shows the reply to ๐ง you.
Booked Train B, 11:30 tomorrow, for โน185. Your PNR is 4821937.
An example with made-up trains, times, prices, seats and PNR. The tool names are ours. The "Think" lines show what the model decides. A real app may not show them. The workers in each step are dark in the row at the top. Your goal is in a white bubble, and the reply you see is in a green one.
Tool or agent?
- ๐ ๏ธA tool does one job when it is asked.
get_weatherreturns the weather for one city, and nothing more. - ๐งญAn agent chooses which tools to use, and in what order, to reach a goal. For the train, the model chose search, then seats, then booking. No code set that order.
The risk with an agent:
- โ ๏ธNo person checks the agent's steps, unless your code adds a check. A wrong booking costs real money, so in round 3 your app asks you before
book_ticketruns.
4What is MCP?
MCP, the Model Context Protocol, is a standard way to connect tools and data to AI apps.
A program that offers tools through MCP is called an MCP server. It is written once, and every app that supports MCP can use it.
Think of a USB-C port. One plug shape fits phones, laptops and chargers from many companies. MCP is one plug shape between AI apps and tools.
- ๐Without a standard, every app writes its own code for every tool. 4 AI apps and 3 tools need 4 ร 3 = 12 connections, each written by hand.
- ๐งฉWith MCP, each tool is written once, and each app learns MCP once. 3 tools, each written once as an MCP server, + 4 apps that support MCP = 7 pieces of work, and all 12 pairs connect.
- ๐ฅ๏ธOne MCP server can offer several tools. The example server in the MCP docs offers two:
calculator_arithmeticandweather_current. - ๐จAn app uses an MCP tool with the same steps as section 2. The app asks the server for its tools (
tools/list) and puts them in the tool list. The model writes a tool request. The app sends it to the server (tools/call) and pastes the result into the prompt.
The LLM talks only to the app, through the prompt. The app connects to each tool through MCP. The three servers are examples; the four apps in the middle box, three named plus yours, can all connect to MCP servers.
MCP does not change the model, which still only writes a tool request. MCP sets the shape of the plug between the app and the tool.
5Why does a model make things up?
A model writes words that have a high chance of coming next, not checked facts. A likely word is usually the true one, but not always (lesson 2), and a wrong answer sounds just as sure as a right one.
Hallucination is when a model writes something false and says it as if it were true.
- ๐For a common fact, the likely answer is the true one. After "The capital of France is", the word "Paris" has by far the highest chance, and it is right.
- โFor a rare fact, the model has no page it can open and read, because it keeps no copy of what it read (lesson 2). Ask for the birthday of a person who is barely mentioned online. It may write a real-looking date that is wrong.
- โณIt doesn't know what happened after its training. Ask for tomorrow's trains from Mumbai to Pune with no search tool, and it may write train times that look real.
- ๐ปIn code, a name can look likely and not exist.
products.sortBy("price")in the chat below looks like real JavaScript, but JavaScript arrays have nosortBy.
How do I sort a JavaScript array of products by price?
Use the built-in sortBy method: products.sortBy("price")
What happens when you run the model's line:
const products = [
{ name: "Pen", price: 20 },
{ name: "Bag", price: 500 },
];
products.sortBy("price");
Node.js stops with this error:
TypeError: products.sortBy is not a function
A made-up chat. Your question is in a white bubble. The orange bubble is the model's wrong answer, said with full confidence. The name looks likely because Lodash, a popular add-on for JavaScript, has a function called _.sortBy.
6How do you reduce made-up answers?
You cannot stop a model from making things up, but you can make it rarer and find it when it happens. Each fix below does one of two things: it makes a made-up answer less likely, or it catches one before it does harm.
- ๐Use RAG, and show the sources (lesson 9). The store's chatbot answers from the policy text your code pasted in, and names the page: "You can return phones, laptops and headphones within 7 days of delivery โฆ (page 12)." A person can open page 12 and check.
- ๐ ๏ธUse tools for facts and maths. With
search_trains, the agent reads tomorrow's real trains instead of guessing them. - ๐ก๏ธUse a low temperature for facts, if you can set it (lesson 6 says where). In lesson 6, temperature 0.5 makes mat 3.6 times as likely as floor, not 1.9 times. The top word wins more often. For a common fact, the top word is the true one (Paris, section 5), so the true word wins more often. It does not help with a rare fact, where the top word itself can be wrong.
- ๐คทLet it say "I don't know". Add to the prompt: "If the policy text does not answer the question, reply: I don't know."
- ๐Check its output in code. Before
book_ticketruns, your code checks that Train B was in the search results. - ๐งโโ๏ธKeep a person checking where a mistake costs a lot. An airline's chatbot told a customer a wrong policy, and a court made the airline follow that wrong policy.
- ๐Or let the LLM check the person. A support person writes the reply, and the LLM checks it. If they disagree, the person looks at the reply again before it is sent.
7What have you learned in these ten lessons?
The course had ten lessons. Here is what each one taught, in one line.
- Lesson 1: a language model guesses the next word, adds it to the text, and guesses again, until it has written a whole answer.
- Lesson 2: training sets a model's parameters, billions (hundreds of crores) of dials, by guessing, checking and nudging again and again.
- Lesson 3: a tokenizer cuts your text into tokens, pieces of text that each have a number, before the model sees it.
- Lesson 4: a model keeps a list of numbers for every token, called its embedding, and words used in the same places get similar lists.
- Lesson 5: attention lets each word look at the words before it and mix in their lists, so "bank" after "river" gets different numbers from "bank" after "money".
- Lesson 6: the model gives every possible next token a chance, and a program draws one by those chances, so the same question can get different answers.
- Lesson 7: after pre-training, two more rounds of training, first on good answers and then on the answers people prefer, turned a text-finisher into an assistant.
- Lesson 8: every token you send and every token the model writes is work for a GPU, so every token costs money.
- Lesson 9: with RAG, your code finds the few chunks of your documents that match the question and puts them into the prompt.
- Lesson 10: a model can ask your code to run tools, but it can still make things up, so give it real facts and check its work.
Rahul's next course covers agents and MCP in more detail.
Where this comes from
- The model only writes text; tool calling = a structured request your app runs and feeds back; the model never executes anything; tool vs agent: Rahul's course blueprint (notes/llm-course-blueprint.md), 1.7 and 10.1.
- Tool definitions,
tool_useandtool_resultblocks,stop_reason"tool_use"and"end_turn", the matchingtool_use_id, resending the tools and the full history: Anthropic's Claude API reference, via the claude-api skill (cached 2026-10-06): theget_weatherexample withname,description,input_schema(curl examples, "tool use"); the manual loop that runs whilestop_reason == "tool_use", appends the assistant's content and returns eachtool_resultwith itstool_use_id, and stops atend_turn(python tool-use guide; shared tool-use concepts). The ids, "Delhi" and "31ยฐC, haze" are ours; the skill's example uses Paris. - 47 รท 12 ร 3.14: 7.34 alone (wrong), 12.2983 with a calculator (right): Hands-On Large Language Models (Alammar, Grootendorst; O'Reilly 2024), ch.7, figure 7-14, PDF p.306-307. The figure is a drawing ("Without tools" / "With tools"), not a recorded test, so the page says "a drawing". 47 รท 12 ร 3.14 = 12.29833โฆ, checked with Node.js on 2026-10-31.
- Agents decide which tools to use and in what order; the Thought / Action / Observation loop; a program runs the action and pastes the result back: Hands-On Large Language Models, ch.7, PDF p.306-310 ("systems that leverage a language model to determine which actions they should take and in what order"; ReAct, figures 7-15 and 7-16). Blueprint 10.1 (think โ call tool โ observe โ repeat). No person checks the steps: ch.7, PDF p.314, "there is no human in the loop to judge the quality of the output or reasoning process", which also suggests asking "whether the output is correct at each step".
- Asking before a tool with side effects runs: claude-api skill, shared tool-use concepts, Security: "For tools with side effects (sending emails, modifying databases, financial transactions), validate inputs and gate destructive operations behind human approval."
- MCP definition, the USB-C comparison, AI applications like Claude connecting to tools and data: modelcontextprotocol.io, "What is the Model Context Protocol (MCP)?": "MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems." and "Think of MCP like a USB-C port for AI applications." modelcontextprotocol.io/docs/getting-started/intro.
- MCP host and server; Claude Code, Claude Desktop and VS Code as hosts;
tools/listandtools/call; the example server's two tools,calculator_arithmeticandweather_current; the app routes the model's tool call to the server and returns the result to the LLM; MCP does not change how apps use LLMs: modelcontextprotocol.io, "Architecture overview" ("MCP Server: A program that provides context to MCP clients"; "MCP focuses solely on the protocol for context exchangeโit does not dictate how AI applications use LLMs or manage the provided context."). modelcontextprotocol.io/docs/2026-07-28/learn/architecture. The 12 vs 7 count is our illustration. - Hallucination: the model writes likely text; likely is usually true, not always: blueprint 1.7, 10.2 and Part 4, misconception 12. No copy of the training text, and the barely-mentioned person's birthday: lesson 2.
- Ways to reduce it: RAG with citations, lower temperature for facts, let it say "I don't know", validate in code, tools for facts and maths: blueprint 10.2. Temperature settings and the mat 3.6 vs 1.9 times floor numbers: lesson 6 (Hugging Face transformers takes them, Hands-On Large Language Models ch.6 p.240-242; from Anthropic API version 2026-10-21 a request that sends
temperaturereturns an error, claude-api skill). - The airline chatbot and the court; the LLM checking the person: How Large Language Models Work (Manning), ch.8, PDF p.150 ("an airline that deployed a chatbot that gave errant policy statements. A court decided that the company had to abide by the policy incorrectly generated and shared by their chatbot", citing BBC, 23 February 2024) and PDF p.152-153 ("have the LLM check the person rather than the person check the LLM"). The book does not name the airline, so neither do we.
sortBy: JavaScript arrays have nosortBy;[].sortByisundefined. The snippet on the page, run in Node.js v24 on 2026-10-31, stops withTypeError: products.sortBy is not a function. Lodash's_.sortBy: "Creates an array of elements, sorted in ascending order by the results of running each element in a collection thru each iteratee", lodash.com/docs/4.17.15#sortBy. The chat itself is made up, as an example of the kind of mistake.- Made up on purpose: the Delhi question and "31ยฐC, haze"; the id
toolu_abc123(the form of the skill's example id); the trains, times, prices, seats and PNR; the tool namessearch_trains,check_seats,book_ticket; the Pen and Bag products. All web pages accessed 2026-10-31.