Tool calling lets an AI application use a defined function when a question needs current information or a calculation. The model proposes a tool name and arguments. The application checks the request, runs an approved function, and supplies the result for the final answer.
The model does not receive unrestricted access to the computer. The application controls which tools exist, what data they can read, and whether an action may be performed.
Follow a tool call
Suppose a customer asks for the shipping charge for a 2 kg parcel. The application offers a shipping_quote function that accepts weight_kg. The model can request a quote, but the application validates the arguments and executes the function.
Example:
User: What is the shipping charge for a 2 kg parcel?
Model requests: shipping_quote({"weight_kg": 2})
Application: validates the request and runs the function
Tool result: {"currency": "INR", "amount": 90}
Final answer: The shipping charge is ₹90.
The price comes from the tool result, not from the model's memory. The result is illustrative; a real quote may also depend on destination, service level, and current rates.
Separate proposal from execution
| Step | Responsible part | What happens |
|---|---|---|
| Choose | Model | Proposes an available tool and arguments. |
| Check | Application | Validates the name, argument types, ranges, and caller permissions. |
| Run | Application | Calls the approved function and captures its result or error. |
| Answer | Model or application | Uses the actual result to respond to the user. |
Do not assume a proposed call has already happened. A response should claim success only after the application reports that the tool ran successfully.
Run only approved functions
A model-produced request is untrusted input. The following Python example allows one read-only calculation and checks the expected arguments before calling it. It shows the application side of tool calling; it does not connect to an AI service.
Example:
def shipping_quote(weight_kg):
if isinstance(weight_kg, bool) or not isinstance(weight_kg, (int, float)):
raise ValueError("Weight must be a number")
if not 0 < weight_kg <= 20:
raise ValueError("Weight is outside the supported range")
return {"currency": "INR", "amount": 50 + 20 * weight_kg}
request = {"name": "shipping_quote", "arguments": {"weight_kg": 2}}
if request["name"] != "shipping_quote":
raise ValueError("Tool is not allowed")
args = request["arguments"]
if set(args) != {"weight_kg"}:
raise ValueError("Unexpected arguments")
result = shipping_quote(args["weight_kg"])
print(result)
Output:
{'currency': 'INR', 'amount': 90}
The program rejects an unknown tool, unexpected argument names, a nonnumeric weight, and a weight outside the supported range. For a tool that reads an order, also verify that the caller is allowed to see that order. For a tool that changes data or sends a message, obtain the required approval before execution.
Handle errors and untrusted results
A tool may fail or return no quote. In that case, say the quote is unavailable instead of guessing an amount. Set sensible limits on repeated calls, and log failures so they can be investigated.
Tool results can also contain untrusted text. A retrieved page may say “ignore previous instructions,” but that text is data, not permission to change the application's rules. Return only the fields needed for the task and keep secrets out of tool results.
Note: Tool calling connects a model to application functions; it does not replace validation, authorization, or human approval for consequential actions.
Conclusion
Tool calling is a controlled handoff: the model proposes, the application validates and executes, and the answer reflects the real result. Narrow tools and clear failure handling keep that boundary understandable and useful.