Function / Tool Calling
20 min
Function calling (or "tool calling") lets a model request that your application run a specific function — but the model NEVER executes anything itself. It only outputs a structured request: a function name and a JSON string of arguments. Your application code is responsible for parsing that, dispatching to the real function, and (typically) sending the result back to the model in a follow-up call so it can use that result in its final answer.
import json
def call_tool(tool_call, registry):
name = tool_call["name"]
args = json.loads(tool_call["arguments"])
fn = registry[name]
return fn(**args)
The registry dict here is doing the same job as Git's is_ancestor or any dispatch-by-key pattern -- mapping a NAME the model provides to the REAL function your application controls, which is also exactly why tool calling is safe: the model can only request functions you've explicitly registered, never arbitrary code.
Write `call_tool(tool_call, registry)`: `tool_call` is a dict with `'name'` (a function name) and `'arguments'` (a JSON string of keyword arguments). `registry` maps function names to actual callables. Parse the arguments, look up the function by name, call it with those arguments, and return the result.
When a model 'calls a function,' what is actually happening — does the model itself execute any code?
You can parse and dispatch a model's function-call request to a real registered function, and understand that the model only requests — your application always does the actual execution.