Visual walkthrough — Tool use and function calling
This page rebuilds the tool-use loop of Tool use and function calling one picture at a time. We assume you know nothing about function calling. By the last figure you will be able to draw the whole cycle from memory.
Let us name the two players before any arrow is drawn, because every figure uses them.
Step 1 — The wall we are trying to cross
WHAT. We draw the starting situation: a user asks a question whose answer lives outside the model.
WHY. Before building machinery, see the problem it solves. "What's the weather in Paris right now?" cannot be answered from training data — the model was frozen months ago. There is a wall between the model's frozen knowledge and the live world.
PICTURE. On the left, the model in a box; on the right, the live world (weather API, database). The red bar is the wall. An arrow from the user bounces off it.

The model can talk about Paris weather but cannot fetch it. The rest of the walkthrough builds a door in the red wall.
Step 2 — Give the model a menu (the schema)
WHAT. Before asking anything, the runtime hands the model a menu of tools it is allowed to request. Each menu item is a function schema.
WHY. The model cannot request a tool it does not know exists. So R first describes each tool in text the model can read. This is the only way M learns the door's shape. We use JSON Schema because it names three things machine-readably: what the tool does, what inputs it needs, and which inputs are mandatory.
Read term by term: name is the label M will echo back to pick this tool; description is the only clue M has for when the tool is appropriate (so it must be written carefully — see 4.3.02-Prompt-engineering-techniques); parameters lists each argument, its type, and whether it is required.
PICTURE. A restaurant-style menu card handed from R to M. One item — get_weather — is highlighted in red, with its three fields called out.

Step 3 — The model writes a call, it does NOT act
WHAT. The user asks "What's the weather in Paris?" The model, having read the menu, outputs structured text — a request naming one tool and filling its arguments.
WHY. The model still only produces text. But now the text is shaped like a form:
name must exactly match a menu item from Step 2, or R will not recognise it. arguments is a JSON object whose keys are the parameters the schema declared. Because this is machine-readable JSON, R can parse it without guessing — the same discipline as 5.2.03-JSON-mode-and-structured-outputs.
Crucial: at this moment nothing has happened in the real world. The model has merely written down a wish. It is like an intern sliding you a sticky note that says "please call the weather API" — the intern did not touch the phone.
PICTURE. The model box emitting a JSON note. The note sits at the red wall — pushed up against the door but not yet through it.

Step 4 — The runtime executes (the door opens)
WHAT. R reads the JSON note, validates it, and calls the real API.
WHY. This is the only step where the outside world is actually touched, and R is in charge, not M. R checks: is name a real tool? Are the arguments the right types? Only then does it run code:
args = json.loads(call.arguments) # parse M's note
if call.name == "get_weather": # is it a known tool?
return weather_api(args["location"]) # R runs it, not MThe order matters: parse → validate → execute. Skipping validation is the security hole of Step 6.
PICTURE. The JSON note passing through the red door; on the far side, R reaching into the live world and pulling back a raw result {"temp":18,"condition":"cloudy"}.

Step 5 — Feed the result back as text
WHAT. R packages the API's answer as a new message and appends it to the conversation, then calls the model again.
WHY. The model has no memory of the API — it only sees text. So R must tell it the result, tagged so M knows this text came from a tool, not a human:
Now the model reads its own earlier request plus the freshly injected answer, and writes the friendly reply: "It's 18 °C and cloudy in Paris." The loop has closed: text out → action → text in → text out.
PICTURE. The raw result travelling back through the door and into the model box; the model emits the final human sentence in red.

Reveal your understanding:
The model's function-call output is executed by
The role: "function" message exists so that
Step 6 — The degenerate case that breaks everything (no validation)
WHAT. We show what happens if R skips the validation of Step 4 and blindly runs whatever the model writes.
WHY. This is the edge case you must cover, because it is where real systems get compromised. Suppose a tool execute_python exists and the model — perhaps steered by a prompt injection hidden in a web page it read — emits:
{"name": "execute_python", "arguments": {"code": "os.system('rm -rf /')"}}If R runs this without a wall, the machine is wiped. The model did not "want" harm — it does not understand consequences; it just pattern-matched some malicious text into a call.
The fix, visually: never put a raw door in the wall. Replace execute_python with allowlisted narrow tools (calculate, read_file(path in /safe)) and run anything risky inside a sandbox with timeouts.
PICTURE. Two doors in the red wall. The left "raw exec" door is an open hole — an X over it. The right "allowlisted + sandbox" door is a narrow gate. Same model note arrives; the safe gate rejects the dangerous call.

Step 7 — The loop repeats: from one call to an agent
WHAT. For hard tasks, one pass is not enough. Steps 3→4→5 become a loop the runtime runs until the model says "done."
WHY. A question like "Fly NYC→Tokyo Tuesday — weather and budget?" needs three separate facts. The model calls get_flight_info, reads the result, then decides to call get_weather, reads that, then check_user_budget. Each result changes what it does next. This reason-then-act cycle is the ReAct pattern (see 6.2.02-Agent-architectures-and-planning).
We can estimate how many loops a task takes. Let
Read it: counts the sub-goals; each needs a tool with probability where is the chance the model could just answer directly; dividing by the per-call success rate inflates the count because failed calls must be retried. Simple weather query: call. Research task: roughly calls.
PICTURE. A circular loop: Model → Call → Runtime executes → Result → Model, with a branch "done?" exiting to the final answer. The active edge (Call) is red.

The one-picture summary
Everything compressed: user in, four numbered arrows around the wall, final answer out. The red door is the whole point of tool use.

Recall Feynman retelling — say it in plain words
A language model is a machine that eats text and spits out text — nothing more. To let it touch the real world, we build a loop. First, my program hands the model a menu describing every tool it may ask for (name, what it does, what inputs it needs). Second, when the user asks something, the model doesn't act — it just writes a note in JSON naming one menu item and filling in the blanks. Third, my program reads that note, checks it's legal, and runs the real API. Fourth, my program takes the API's answer and pastes it back into the conversation as a new message tagged "this came from a tool." Fifth, the model reads that answer and writes the friendly reply. The single most important line to remember: the model only ever writes wishes; my program decides whether to grant them. That split is the wall that keeps a hijacked model from wiping the disk — so we never expose a raw "run any code" door, only narrow allowlisted gates inside a sandbox. For hard tasks the middle three steps repeat in a loop until the model says it's finished, and roughly the number of loops is the task's sub-goals divided by how often each call succeeds.
Related: Tool use and function calling · 6.2.02-Agent-architectures-and-planning · 5.2.03-JSON-mode-and-structured-outputs · 4.3.02-Prompt-engineering-techniques · 7.1.01-RAG-fundamentals