Why Tools

From Talking to Doing

On its own, a model can only produce text. With tool use (also called function calling) you describe functions to the model; when it needs one, it replies with a structured request like get_order_status(order_id="SE-10423"). Your code runs the function and sends back the result. The model then writes the final answer using real data.

Without toolsWith tools
"I can't see your order"Looks up the real order status
Guesses arithmeticCalls a calculator
Knows facts up to its training cut-offCalls search or your database for live data
Only suggests actionsCreates a return request (with your checks and approval)

Note: The model never runs code itself. It only asks. Your app decides whether to run the tool, which keeps you in control of security and permissions.

A Tool Request Is Just Structured Output

Example

Think of a tool call as the model filling in a form that your code then dispatches. A tiny dispatcher:

def get_order_status(order_id):
    return {"order_id": order_id, "status": "shipped"}

def calculator(expression):
    a, op, b = expression.split()
    return {"result": {"+": float(a) + float(b), "*": float(a) * float(b)}[op]}

REGISTRY = {"get_order_status": get_order_status, "calculator": calculator}

# what a model's tool request looks like (stand-in values)
requests = [
    {"name": "get_order_status", "input": {"order_id": "SE-10423"}},
    {"name": "calculator", "input": {"expression": "1299 * 3"}},
    {"name": "delete_database", "input": {}},
]
for r in requests:
    fn = REGISTRY.get(r["name"])
    print(r["name"], "->", fn(**r["input"]) if fn else "refused: unknown tool")

Output

get_order_status -> {'order_id': 'SE-10423', 'status': 'shipped'}
calculator -> {'result': 3897.0}
delete_database -> refused: unknown tool