A language model reads text and writes text. It cannot look up an order, charge a card or send an email. Tool calling is how an application lets it ask for those things: the request lists the tools the application offers, each with a name, a description and a JSON schema for its arguments, and the model may answer with a request to call one instead of with prose.
Every exchange in the film is a real recording. The questions were sent to `google/gemini-3.8-flash` through OpenRouter at temperature 0 on 11 September 2026, with a system prompt for an online shop and two tools, `get_order_status` and `cancel_order`. The handler in the film's code editor is the real code that ran: a regular expression that checks the order id, a one-row order table, and a guard that refuses to cancel anything that is not still being processed.
The traced request is the whole mechanism. The customer asks where order A-1042 is. The model's first turn contains no text at all, only a tool call naming `get_order_status` with the argument `{"order_id": "A-1042"}`. Your code checks the id, reads the table, and returns the row: shipped with DPD on 9 September, arriving 14 September. That result is sent back to the model as a tool message, in a second request that repeats the conversation, and only then does the model write the answer the customer sees.
The part people miss is where the model's role ends. It writes a request, and nothing more. Everything that happens to that request happens in your code: whether the arguments parse, whether the id is well formed, whether this customer may touch this order, and whether the action runs at all. When the model asked to cancel A-1042, the order had already shipped, so the application refused and said why, and the model passed the refusal on. Validation and permissions belong on your side, because the model cannot enforce them.
The failure mode is forgetting that the trip has two legs. Stop after the first turn and the customer receives an empty message, because the text of a tool-calling turn is usually empty. Worse, send the result back empty, as a bug in the plumbing might, and the model does not say that something went wrong. In three runs of three it told the customer it could not find order A-1042, an order that had shipped two days earlier. A missing result reads to the model like a negative result.
Errors should travel the same road as data. When the customer typed A-1402, the lookup failed, and the application returned a structured error rather than nothing. The model turned it into a polite request to double-check the order number, which is the right answer, because the error said exactly what happened.
The takeaway is a division of labour. The model proposes a call and phrases the reply. Your code decides whether the call is valid and allowed, runs it, and always sends a result back, including when the result is an error.
The maths
- One tool call is two model calls
The first call returns a tool call and no text: in all four recordings the model sent an empty reply alongside the request. The answer only exists after a second call that carries the call and its result r back in the messages.
- Your code sits in the middle
The model picks f and writes the arguments a as JSON. It never runs f. Your application parses a, checks it, decides whether the call is allowed, runs the function, and chooses what r says. The cancel request here was refused by one line of application code.
- An empty result is still an answer
When the tool message came back empty, the model told the customer it could not find an order that had shipped two days earlier, in three runs of three. It reads a missing result as a negative result, so a bug in the plumbing becomes a confident wrong answer.
- Errors are data
Returning a structured error, rather than throwing or returning nothing, lets the model explain the failure in terms the customer understands. The typo exchange is exactly that: A-1402 does not exist, your code said so, and the reply asks the customer to check the number.
Transcript
The narration, chapter by chapter. A timestamp opens the film at that moment.
- 0:00Models cannot act
- A language model can only write text, so when a customer asks where order A-1042 is and when it will arrive, the model has no way to look it up by itself.
- 0:12The request
- So instead of answering, it writes a tool call that fits the schema you gave it: a small card naming get_order_status with the order id A-1042, and its reply text is empty.
- 0:26Your code runs it
- The card crosses to your application, and it is your code, not the model, that parses the arguments string, checks the id, reads the order table, and gets back shipped with DPD, arriving 14 September.
- 0:39Back to the model
- Only when that result goes back into the conversation as a tool message with the same call id does the model write the answer: your order A-1042 has shipped via DPD and should arrive on 14 September.
- 0:53Stopped halfway
- Here is the first failure mode: stop after the first turn, and the customer gets an empty reply, because that turn was only a tool call.
- 1:03Result lost
- Worse, send the result back empty, and the model does not report an error: it tells the customer it could not find an order that shipped two days ago.
- 1:14Errors travel too
- Errors travel the same road: a customer types A-1402, your code returns order not found, and the model turns that into a request to double-check the number, which is exactly right.
- 1:26Who decides
- Cancelling shows who is in charge: the model asks to cancel A-1042, your code refuses because it has shipped, so validate every call on your side and always send the result back.
Also available as captions (WebVTT), the video file and a Markdown copy of this page.
Related terms
- ToolA tool is a named action, with a typed input schema, that a model is allowed to call. Tools are how a model that can only produce text gets to actually do things: read a file, run a command, search the web.
- Tool callA tool call is the model’s request to use a tool: it names the tool and supplies the arguments, then pauses. It has not run anything. Your harness is what actually executes the action.
- Tool resultA tool result is the output of running a tool, fed back into the conversation so the model can use it. It is tied to the tool call that requested it, and it is how the model sees the consequences of its own actions.
- HarnessThe harness is the code wrapped around a model that builds requests, runs tools, manages context, and enforces permissions. It is the agent minus the model, and it is where most of the real engineering lives.
- TurnA turn is one round of the agent loop: your input, the model doing its work (possibly several tool calls), and its response. A single turn can span many provider requests.
More visualisations
Embed this film
Paste this into a post, a course page or a newsletter. The film plays in place, with the same controls as here, and credits the source.