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.

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:

  1. Your app tells the model which tools exist: each tool's name, what it does, and what it needs.
  2. When a tool would help, the model writes a tool request instead of an answer.
  3. Your code runs the tool.
  4. Your app sends the result to the model.
  5. 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.

What the LLM sends to your app (simplified):
{
  "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.

What your app sends (simplified: the tool list is sent again too, and the first two messages are shortened):
"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.

What the LLM sends to your app (simplified):
{
  "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.

Step 1 of 6

Three things to know about tool calling:

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:

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:

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.

๐Ÿ’ญ ThinkFirst I need tomorrow's trains. ๐Ÿ› ๏ธ Actsearch_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.

๐Ÿ’ญ ThinkTrain B is the cheapest. Does it have seats? ๐Ÿ› ๏ธ Actcheck_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.

๐Ÿ’ญ ThinkSeats are free. Book Train B. ๐Ÿ› ๏ธ Actbook_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.

Step 1 of 5

Tool or agent?

The risk with an agent:

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.

๐Ÿค– LLMwrites tool requests
โ‡„prompt
๐Ÿง‘โ€๐Ÿ’ป AI appClaude Desktop, Claude Code, VS Code, your app
โ‡„MCP
๐ŸŒฆ๏ธ Weather server
๐Ÿ“… Calendar server
๐Ÿ—„๏ธ Database server

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.

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.

7What have you learned in these ten lessons?

The course had ten lessons. Here is what each one taught, in one line.

  1. Lesson 1: a language model guesses the next word, adds it to the text, and guesses again, until it has written a whole answer.
  2. Lesson 2: training sets a model's parameters, billions (hundreds of crores) of dials, by guessing, checking and nudging again and again.
  3. Lesson 3: a tokenizer cuts your text into tokens, pieces of text that each have a number, before the model sees it.
  4. 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.
  5. 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".
  6. 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.
  7. 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.
  8. Lesson 8: every token you send and every token the model writes is work for a GPU, so every token costs money.
  9. Lesson 9: with RAG, your code finds the few chunks of your documents that match the question and puts them into the prompt.
  10. 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.

← Lesson 9  ·  All lessons

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_use and tool_result blocks, stop_reason "tool_use" and "end_turn", the matching tool_use_id, resending the tools and the full history: Anthropic's Claude API reference, via the claude-api skill (cached 2026-10-06): the get_weather example with name, description, input_schema (curl examples, "tool use"); the manual loop that runs while stop_reason == "tool_use", appends the assistant's content and returns each tool_result with its tool_use_id, and stops at end_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/list and tools/call; the example server's two tools, calculator_arithmetic and weather_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 temperature returns 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 no sortBy; [].sortBy is undefined. The snippet on the page, run in Node.js v24 on 2026-10-31, stops with TypeError: 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 names search_trains, check_seats, book_ticket; the Pen and Bag products. All web pages accessed 2026-10-31.