advanced26 min

Tool and Function Calling

Let a model request actions from your code, instead of only producing text.

What you'll learn

  • Explain the tool-calling request/response cycle
  • Define a small typed tool registry
  • Dispatch a requested tool call safely, including for an unknown tool

Prerequisites

Explanation

By default, a language model can only produce text — it can't check today's weather, look up a real order status, or update a database. Tool calling (also called function calling) bridges that gap: you describe a set of available "tools" to the model (a name, a description, and a typed schema of parameters), and instead of guessing an answer, the model can respond with a structured request like "call the getOrderStatus tool with { orderId: '12345' }."

Critically, the model never actually executes anything — it only produces a structured request. Your own code (which you fully control) receives that request, decides whether to honor it, actually runs the corresponding function, and sends the result back to the model as another message, so it can use that result to continue the conversation or produce a final answer. This request/response cycle usually looks like:

  1. You send the user's message plus a list of available tool definitions.
  2. The model replies asking to call a specific tool with specific arguments (or just replies normally with text if no tool is needed).
  3. Your code executes that tool (or refuses/validates first) and returns the result.
  4. The model incorporates the result and produces its next message — which might be a final answer, or another tool call.

Designing tools well matters as much as designing prompts. Each tool should have a narrow, clearly-described purpose, typed parameters (so malformed requests are easy to catch before execution), and should return structured results, including structured errors — never let a tool call crash your whole request pipeline; a failed lookup should come back as { error: "order not found" }, not an unhandled exception.

Because the model decides when and with what arguments to call a tool, you must treat every requested tool call as untrusted input from the model — validate arguments, enforce authorization (can this user actually access this order?), and never expose a tool that performs an irreversible or sensitive action without additional safeguards. This is the direct foundation for the agents lesson next, where multiple tool calls get chained together in a loop.

Example

A tiny mock tool registry and dispatcher (no real model call — this simulates the model 'requesting' a tool call as a plain object).

const tools = {
  getOrderStatus: (args) => {
    const orders = { "1001": "shipped", "1002": "processing" };
    const status = orders[args.orderId];
    return status ? { status } : { error: "order not found" };
  },
};

function dispatchToolCall(request) {
  const tool = tools[request.name];
  if (!tool) {
    return { error: `Unknown tool: ${request.name}` };
  }
  return tool(request.arguments);
}

// Pretend this object is what the model asked for.
console.log(dispatchToolCall({ name: "getOrderStatus", arguments: { orderId: "1001" } }));
console.log(dispatchToolCall({ name: "getOrderStatus", arguments: { orderId: "9999" } }));
console.log(dispatchToolCall({ name: "deleteEverything", arguments: {} }));

Try it yourself

Add a new tool to the registry and dispatch a call to it.

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Guided exercise

Guided exercise

Complete `dispatchToolCall(tools, request)` where tools is an object mapping tool names to functions, and request is `{ name, arguments }`. Call the matching tool with request.arguments and return its result, or return `{ error: 'Unknown tool: ' + name }` if it doesn't exist.

Checks: Dispatches to an existing tool correctly · plus 1 hidden check

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Independent exercise

Independent exercise

Write a tools object with a `lookupBook` tool that takes `{ title }` and returns `{ price }` for a small hardcoded catalog (at least 2 books), or `{ error: 'book not found' }` otherwise. Then write `handleRequest(request)` that dispatches to this tools object the same way as the guided exercise, additionally returning `{ error: 'invalid arguments' }` (without calling the tool) if `request.arguments` is missing or not an object.

Checks: Looks up an existing book's price · Handles an unknown book gracefully · plus 1 hidden check

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Common mistakes

  • Letting a tool call execute a sensitive action without validating its arguments or checking authorization first.
  • Letting a failed tool call throw an unhandled exception instead of returning a structured error the model can react to.
  • Assuming the model directly executes code — it only ever requests a call; your code stays in control of what actually runs.

Knowledge check

Knowledge check

1. Who actually executes the requested tool/function?
2. What should a tool return when it fails, instead of throwing an unhandled exception?
3. Why must tool call arguments from the model be validated before use?

Takeaway

The model only asks for actions in structured form; your code stays firmly in control of whether and how they run.

Summary

Tool calling lets a model request a structured function call with typed arguments instead of only producing text. Your application code dispatches, validates, and executes that request, returning structured results (including structured errors) back to the model to continue the conversation.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.