Function calling lets the model decide which tool to call, with what args, in a schema-validated JSON envelope. The orchestrator runs the tool, returns the result, the model decides what’s next. Without function calling, the model emits prose like “call lookup(order_id=8821)” and you regex-parse it.
Define tools: [{”name”: “lookup”,"parameters":{"properties":{"order_id":``{”type”: “string”`}“}}}]; pass to the model.
The model returns tool_calls with name+args (JSON). Orchestrator runs, returns tool result; model decides next step.
tool_choice=“auto” lets the model decide OR set “required” to force a call.
Validate tool names against an allowlist before dispatch: ALLOWED = {"lookup","refund","cancel_order"}.
free text -> "call lookup 8821" -> regex
function calling -> tool_calls JSON -> dispatch
(schema-validated, no regex)
Function calling is the cleanest primitive for “model picks the tool”. Skip prose tricks.